[英]c++, std::atomic, what is std::memory_order and how to use them?
[英]C++ use of std::atomic<A> for accessing a memory pool
object 有一個由malloc()
分配給它的 memory 池。 這個 object 使用std::atomic<A> *
訪問 memory 池進行讀寫。 <A>
可以是 class,它是普通可復制類型或任何標准類型。 這個讀寫memory池的object可以被不同的線程調用。
如果線程獲得對原子 object 的引用,例如指向 memory 池的特定 memory 地址,然后對 object 執行一些邏輯,那么在此期間另一個線程是否可以引用同一個原子 object? 這個線程是等到另一個線程“釋放”這個 object 還是繼續獲取另一個尚未引用的 object? 以下代碼是此類用例實現的算法:
std::atomic<Record> * it_record{&memory_address}; -> memory_address is obtained by malloc()
for(size_t i{0U}; i < m_nbr_record; ++i) {
Record tmp = *it_record;
if (tmp == target_record) {
*it_record = new_record;
found = true;
break;
}
++it_record;
}
如果線程獲得對原子 object 的引用,例如指向 memory 池的特定 memory 地址,然后對 object 執行一些邏輯,那么在此期間另一個線程是否可以引用同一個原子 object?
是的。 通過原子變量訪問 object 只能保證執行單個原子操作,這樣其他線程就不會干擾。 在您的示例中,讀取和寫入都是原子操作。
這個線程是否等到這個 object 被另一個線程“釋放”[...]?
不,這就是互斥鎖的作用。 同樣,對於原子,單個操作是原子的,而不是一系列操作。
對於您的特定用例, 比較和交換 (CAS)看起來應該有效。
for(size_t i = 0; i < m_nbr_record; ++i) {
if(it_record[i].compare_exchange_strong(
target_record, new_record)) {
found = true;
break;
}
}
正確和高效是兩件截然不同的事情。 這種操作有些不尋常,而且效率很低。 您的算法描述太模糊,無法提供任何有意義的建議,但 memory 池聽起來非常像無鎖堆棧最好的服務
如果您堅持自己的設計,請檢查是否可以將其更改為讀取 + CAS 循環,以避免在找到正確的元素之前使用昂貴的 CAS。
for(size_t i = 0; i < m_nbr_record; ++i) {
if(it_record[i].load(std::memory_order_relaxed) != target_record)
continue;
if(it_record[i].compare_exchange_strong(
target_record, new_record)) {
found = true;
break;
}
}
您還應該檢查 CAS 是否可能使用較弱的 memory 訂單之一,但這取決於您的用例的具體情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.