簡體   English   中英

C++ 使用 std::atomic<a>訪問 memory 池</a>

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM