[英]Is writing std::deque at different memory locations concurrently thread-safe?
我有一個std::deque<std::pair<CustomObj, int>>
,它在啟動並發塊時不會改變大小。
並發塊讀取deque
每個CustomObj
並設置int
。
我可以保證deque不會改變大小因此它不會重新分配,並且每個線程只會訪問deque的內存塊而不是其他線程的內存塊。
是否會導致未定義的行為同時讀寫? 我應該把寫作和閱讀放在互斥區嗎?
令我驚訝的是,在目前的標准本身中,實際上有一個非常明確的部分:
(C ++ 17,26.2.2集裝箱數據競賽,2)
- 盡管有20.5.5.9,但當同一容器中不同元素中包含的對象的內容(
vector<bool>
除外)同時修改時,需要實現以避免數據爭用。
您也可以毫無顧慮地撥打以下訪問者:
- 為了避免數據爭用(20.5.5.9),實現應考慮以下函數為const:
begin, end, rbegin, rend, front, back, data, find, lower_bound, upper_bound, equal_range, at
和,除了關聯或無序的關聯容器,operator[]
。
由於std::deque
既不是例外,你可以同時調用任何這些函數來獲取不同的元素並進行修改。 只需確保從同時訪問和修改元素的並行區域中正確隔離對容器本身的任何修改。
例如,這是錯誤的:
std::dequeue<...> dq;
#pragma omp master
{
...
dq.emplace(...);
}
// no implicit barrier here,
// use omp barrier or change to omp single instead of master
#pragma omp for
for (... i; ...)
dq[i].second = compute(dq[i]);
只要你可以保證deque
的大小不會改變,並且只有一個線程會寫入特定元素,那么是的,這是安全的。 當您嘗試修改deque
(更改其大小)或者有多個線程讀取和寫入deque
的單個元素時,您只會遇到問題。
您可以體驗到的一件事是虛假共享 。 這是具有多個線程使用的元素的單個高速緩存行的過程。 由於線程寫入會弄臟緩存行,因此整個事情需要重新同步,這將損害性能
所有標准容器的Arule是:
這只是適度過於強烈。 你可以做一些違反上述規則的事情而不是標准下的競爭條件。
在標准中,這通常用容器上的const
方法表示。 read方法是const
,write方法不是const
。 例外是begin()
和end()
以及data()
(只返回迭代器的方法)非const
計數為const
。
對於迭代和元素訪問,它的措辭是迭代器失效。 許多操作使迭代器無效,並且如果迭代器以其未使用的方式使其無效,則它是競爭條件。
作為上面的經驗法則說“不”但標准說“ok”的情況的一個例子:
您可以擁有地圖和對存儲的地圖中的值的引用。 您可以在另一個線程將鍵值對添加到地圖時編輯該值。
由於沒有迭代器被地圖無效,而你沒有碰到鑰匙,我相信沒有競爭條件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.