假設C++ 11,你想做一個原子fetch_and_add,然後處理結果。
例如:
std::atomic<int> counter = 20;
if (counter.fetch_sub(1) == 1) /* return value is old value */
{
Widget* widget = nullptr;
swap(some_widget, widget);
}
如果在計數器跨線程使用,我們需要確保編譯器和硬件不弄亂內存排序。 std::atomic<>.fetch_sub()
的默認排序是std::memory_order_seq_cst
,這樣做會很好,但是如果您想贏得例如ARM64,你可以減少到std::memory_order_acquire
。
爲了使交換操作符合上述方案,我們確實需要一個鎖。 有趣的是,這適合於「雙重檢查鎖定」模式,這是一些人所不希望的,但在這裏非常有用 - 對於大多數操作你不會受到鎖的影響,但是當它重要時,它就在那裏。 這是如何:
std::atomic<int> counter = 20;
std::mutex counterLock;
std::atomic<Widget*> some_widget;
...
if (counter.load(std::memory_order_acquire) > 5) /* first check whether we're "close enough" */
{
/* only lock when needed */
std::lock_guard<std::mutex> templock(counterLock); /* free lock whenever we exit this scope */
if (counter.fetch_sub(1) == 1) /* return value is old value */
{
Widget* oldwidgetpr = some_widget.exchange(nullptr, std::memory_ordering_release);
/* do whatever you need to do with the oldwidgetptr */
}
}
else
counter.fetch_sub(1);
有兩個**/* *結束的原子性\ */**,其中一個*真*結束?我懷疑有沒有辦法在原子中執行多個語句而不使用鎖定。 – davidshen84
另外,你不想*刪除*'some_widget',你只是想把它分配給'nullptr'? – Barry