2008-12-12 129 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不會提供任何安全性。線程安全只能通過鎖定或其他同步原語來實現。