2016-12-03 111 views
0

是否有一個c + +容器(單個寫入器,許多讀者)用於存儲總是讀/寫(lockfree)的單個值?閱讀過時的版本是好的。在C++中的單個對象的線程安全的容器

我想到了這樣的事情:

template <class T> 
class Container { 
    bool active = 0; 
    T object[2]; 
public: 
    void writeData(T t) 
    { 
     object[!active] = t; 
     active = !active; 
    } 
    T readData() 
    { 
     return object[active]; 
    } 
}; 

一個問題,我認爲:

Read thread reads active = 0 
Write thread happens (active = 1) 
another Write thread starts and writes to 0 
Read thread reads the data which is currently written to 

原因活躍的是不是原子,但因爲它是一個布爾值,只有一個寫線程發生一次,兩種可能的值都是可以接受的。

+0

您需要考慮編譯器優化代碼時會發生什麼。代碼可能會被省略,因爲如果編譯器可能已經在另一個線程中更新了,則編譯器將不會意識到需要重新讀取這些值。如果編譯器優化以刪除不必要的讀取(或寫入),您可能永遠不會看到更新的值。 –

回答

0

不是一個完整的解決方案,但如何可以這樣做的想法:

假設你要存儲值爲非基本類型(否則只使用atomic,見http://en.cppreference.com/w/cpp/atomic/atomic),那麼你可以做的是使用像atomic<Container*> current_container;作爲中心指向你的對象。並在您的每個更新writer準備新的完全形成Container對象與更新的數據,當它完成設置current_container指向一個新的對象。

注意,存在這種方法的幾個注意事項:

  • 的作家,你不能馬上刪除Container舊的情況下更換,因爲有些讀者可能會使用它是靜止後。如果您的Container將被動態分配,那麼這可能會變得棘手。你可能想使用std::shared_ptrcurrent_containeratomic_exchage爲手段來改變它的值(見http://en.cppreference.com/w/cpp/memory/shared_ptr/atomic

  • 這種方法將需要作家,每次更新,充分準備的Container一個新版本 - 這可能是昂貴的,如果Container大並且如果它的拷貝很貴

0

我不知道隨時可以使用的實現。但有一個努力獲得這樣的設施到C++標準: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0561r3.html

該文件顯示,爲了完全線程安全和某種形式的回收,你有一個相當複雜的問題來解決。無論如何,論文中的規範應該有助於創建正確的實現。