2008-12-12 114 views
9

如何const(指针,引用和成员函数),在C++线程安全的帮助?线程安全和`const`

+0

它没有。仅仅因为对变量的引用是const,并不意味着没有对该变量的非const引用。 – 2016-05-25 13:07:53

+0

@ChrisBecke无可否认,这个http://stackoverflow.com/questions/14127379/does-const-mean-thread-safe-in-c11是一个更好的问题,问得更多事后。我认为那里的答案表明,一个“不”这个词是不够的。 – 2016-05-31 10:23:24

回答

6

多线程的主要问题是可变性。 const限制了这一点,但是由于你可以抛弃常量,所以它不是万无一失的。

14

任何不变(即unchangable)数据本身是线程安全的 - 有没有风险多线程并发读取相同的只读数据,因为它永远不会改变!

标记在C++中的变量为const使得只读并因此线程安全的。

+0

假设你没有在任何地方使用mutable ;-) – 2008-12-12 09:30:42

+1

并假设它的初始化是线程安全的。 – xtofl 2008-12-12 10:17:48

6

一个const成员函数不应该改变的状态,这使得它的安全,同时从多个线程调用。然而,线程安全不是const的目的,C++提供了mutable关键字和const_cast,这意味着const实际上并不能保证线程安全,因此不应该依赖此目的。

4

Const函数不是线程安全的。通常,您可以同时从不同线程调用const对象方法,但是如果从不同线程调用非const和const方法,则会出现竞争条件。选中此项:

class Foo 
{ 
    size_t size_; 
public: 
    ... 
    size_t get_size() const 
    { 
     return size_ 
    } 
}; 

class Bar 
{ 
    boost::shared_ptr<Foo> foo_; 
public: 
    //accessor 
    size_t get_size() const 
    { 
     size_t size = 0; 
     if (foo_) 
      size = foo_->size(); 
     return size; 
    } 
    //modifiers 
    void init() 
    { 
     foo_ = new Foo; 
    } 

    void clear() 
    { 
     foo_ = boost::shared_ptr<Foo>(); 
    } 
}; 

如果有人调用init方法,然后同时调用clear和get_size方法,将导致访问冲突。您必须使用读写锁定语法。可以同时调用多个访问器,并且只能同时调用一个修饰符。 例:

class Bar 
{ 
    boost::shared_ptr<Foo> foo_; 
    mutable tbb::spin_rw_mutex lock_; 
public: 
    //accessor 
    size_t get_size() const 
    { 
     size_t size = 0; 
     //lock modifiers 
     rw_mutex_type::scoped_lock lock(mutex, false); 
     if (foo_) 
      size = foo_->size(); 
     return size; 
    } 
    //modifiers 
    void init() 
    { 
     //lock accessor and modifiers 
     rw_mutex_type::scoped_lock lock(mutex, true); 
     foo_ = new Foo; 
    } 

    void clear() 
    { 
     //lock accessor and modifiers 
     rw_mutex_type::scoped_lock lock(mutex, true); 
     foo_ = boost::shared_ptr<Foo>(); 
    } 
}; 

TBB :: spin_rw_lock是从threading builing blocks library互斥类

4

C++常量允许非const混叠,例如:

Foo myVar; 
const Foo* ptr1; 
Foo* ptr2; 

鉴于此,常量不提供保证,以数据的不变性,即使你没有做任何演员或任何事情来解决它。如果你通过ptr1访问myVar,你不能通过ptr1来改变它(假设我的语法是正确的;这就是意图)。但是,它仍然可以通过ptr2来改变。你真正想要的是一个单独的不可变构造。这在C++中不存在。

3

Const和线程安全是正交的概念。

以一个const函数为例:一个类可能同时具有const和非const函数,并且一个线程可能正在调用一个非const函数,该函数在另一个线程处于const函数的同时修改该对象。在这种情况下,标记函数const不会提供任何安全性。线程安全只能通过锁定或其他同步原语来实现。