假設我有C++中的結構和類:多線程原子儲存在碳多重值/負載++
struct Vec {
double x;
double y;
double z;
}
class VecTracker {
Vec latest_vec;
std::atomic<double> highest_x;
std::atomic<double> highest_y;
std::atomic<double> highest_z;
//updates highest_x, highest_y, highest_z atomically
void push_vec(const Vec& v);
double get_high_x() const;
double get_high_y() const;
double get_high_z() const;
//returns Vec consisting of snapshot of highest_x, highest_y, highest_z
Vec get_highs() const;
}
我得[R讀線程和一個寫線程。作者線程將更新零個或多個highest_*
成員。如果讀者線程調用get_highs()
,則需要讀寫器線程讀取highest_x
,highest_y
等以產生向量,來自當前調用寫入器線程push_vec()
函數的所有寫入對於讀取器線程可見,對於讀取器線程。
現在,我知道如果Vec
足夠小,我可以使用std::atomic<Vec>
。問題是,如果它太大,則不能使用這些存儲/加載的本機CPU指令。是否有任何方法可以使用std::atomic_thread_fence
來保證在讀取器線程拾取它之前多個原子寫入由寫入器線程提交?也就是說,保證在讀者線程看到它們之前,寫入器線程的所有寫入操作都會被提交。還是std::atomic_thread_fence
只提供線程內的重新排序保證?目前,僅爲每個成員使用.store(std::memory_order_release)
似乎並不能保證所有三個商店都在任何閱讀之前發生。
很顯然,我可以在這裏使用鎖,但理想情況下我想找到一種方法來使此數據結構無鎖定。
我知道我可以將highest_x
,highest_y
和highest_z
放在一個結構中,並在堆上分配它的兩個副本,在每次寫入後自動交換指針。這是唯一的方法嗎?
啊哈。是的,我認爲只有本地的原子操作實際上可以保證原子行爲。看起來指針交換是當時的方式。 這裏不能真正使用Mutex或螺旋鎖,因爲會有非常大的爭用,我想保證進度。 – alfalfasprout
我搜索了,但找不到任何對CMPXCHG32B指令的引用。如果這樣的指令實際存在,在這種情況下就足夠了,因爲在今天的大多數系統中,三倍只能達到24B。你有沒有把它與CMPXCHG16B混淆?在那種情況下,你的觀點更有意義。 –
@ErikNyström,100%是!感謝您的發現。 – SergeyA