2013-10-16 49 views
4

我有一個問題,我需要能夠自動更新兩個uint64_t的同時。很容易以原子方式編寫它們中的每一個(例如,有兩個std::atomic<uint64_t>),但這仍然會導致一個更新但另一個不更新的情況。使用鎖和互斥鎖也很容易。你能原子地寫兩個uint64_t嗎?

但是我想同時寫入,沒有任何類型的鎖,這樣我仍然可以使用類型爲uint64_t的成員變量,以便讀取時不會鎖定。這是因爲我的用例涉及很多很多次的閱讀,但是很少寫(〜讀1x/ms,寫1x/5分鐘)。可能嗎?如果是這樣,怎麼樣?

+0

嗯....聽起來像你正在尋找在錯誤的類型鎖定模式,或許。 –

+1

C++不可能。如果您使用的是x64 CPU,則可以使用「CMPXCHG16B」指令,如果兩個64位值是並排和16字節對齊的。 –

+1

您可以無鎖地訪問的對象取決於硬件。如果硬件不支持128位原子對象,那麼你根本無法做到。原子模板是抽象出這種差異的方法,在需要硬件的硬件上使用鎖定,並在可用硬件支持的情況下使用鎖定。 – bames53

回答

0

我不認爲有可能直接做,但你可以做的是使用software transactional memory techniques來僞造它。尤其是,您可以使用uint64_t對的無鎖環形緩衝區。在這種配置下,寫入環形緩衝區的非活動元素是非安全的,因爲沒有人會從環形緩衝區的那個元素讀取,直到「當前值索引」被原子更新爲寫入結束(這可能是因爲索引可以是int32_t)。

注意事項:如果您可以保證在短時間內不會有太多的寫入值(其中'太多'表示'超過環中的插槽數量'緩衝)。另外,我建議找到一個實現這個功能的STM庫,而不是自己動手編寫,因爲無鎖編程出人意料地很難100%正確。

2

爲什麼不創建一個類的兩個uint64_t中的,並用它來與的std ::原子

class atomic128 { 
    uint64_t a1, a2; 
}; 

,然後只用std::atomic<atomic128>

另一種辦法是使用SSE加載/存儲

編輯:

爲了對某些用戶定義的UDT使用std::atomic<UDT>,此typ e必須有一個簡單的複製分配操作符。

Does std::atomic<std::string> work appropriately?

+0

這個名字就是一個例子,它不是很重要。 OP應該決定最能反映他的工作的那個。無論如何,我只是編輯了答案 –

+0

-1在任意類型上實例化原子「」,而沒有提供完整的專門化類型,這幾乎從來都不是你想要的,並且肯定會導致任何程序員的臉上有驚訝的表情,碼。 – ComicSansMS

+0

但是,請注意,對'std :: atomic '類型的對象的原子更新不需要無鎖。 –