在不同的内存位置同时编写std :: deque是否是线程安全的?

qui*_*uss 12 c++ multithreading openmp c++11

std::deque<std::pair<CustomObj, int>>启动并发块时,我的大小不会改变.

并发块读取每个CustomObjdeque并设置int.

我可以保证deque不会改变大小因此它不会重新分配,并且每个线程只会访问deque的内存块而不是其他线程的内存块.

是否会导致未定义的行为同时读写?我应该把写作和阅读放在互斥区吗?

Zul*_*lan 16

令我惊讶的是,在目前的标准本身中,实际上有一个非常明确的部分:

(C++ 17,26.2.2集装箱数据竞赛,2)

  1. 尽管有20.5.5.9,但当同一容器中不同元素中包含的对象的内容vector<bool>同时修改时,需要实现以避免数据争用.

您也可以毫无顾虑地拨打以下访问者:

  1. 为了避免数据争用(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]);
Run Code Online (Sandbox Code Playgroud)


Nat*_*ica 7

只要你可以保证deque不会改变大小并且只有一个线程会写入特定元素然后是,那就安全了.当您尝试修改deque(更改它的大小)或有多个线程读取和写入内部的单个元素时,您只会遇到问题deque.

您可以体验到的一件事是虚假共享.这是具有多个线程使用的元素的单个高速缓存行的过程.由于线程写入会弄脏缓存行,因此整个事情需要重新同步,这将损害性能

  • 要防止错误共享,请尝试使用相同的线程访问相邻元素.通常你可以使用标准的`#pragma omp for`. (3认同)