Tar*_*arc 5 c++ multithreading thread-safety stddeque
来自emplace_back()以下文档的摘录:
- 迭代器有效性
与此容器相关的所有迭代器都是无效的,但指针和引用仍然有效,指的是它们在调用之前引用的相同元素.
- 数据竞赛
容器已修改.
调用不访问任何包含的元素:同时访问或修改它们是安全的(尽管请参见上面的迭代器有效性).
以及以下文档的摘录operator[]():
- 数据竞赛
访问容器(const和非const版本都不会修改容器).
可能会访问或修改元素n.同时访问或修改其他元素是安全的.
因此,鉴于deque的某个实例至少有一个元素,通过访问它operator[]()并同时调用emplace_back()容器确实是线程安全的?
我倾向于说它是,但不能决定"访问" emplace_back()的文档是否包括使用operator[]()如下:
int access( std::deque< int > & q )
{
return q[ 0 ];
}
void emplace( std::deque< int > & q , int i )
{
q.emplace_back( i );
}
Run Code Online (Sandbox Code Playgroud)
其中两个函数同时调用,或者"访问"仅适用于已经采用某些引用或指针的元素:
std::deque< int > q { 1 };
auto * ptr = & q[ 0 ]
std::thread t1 ( [ ptr ]{ * ref = 0; } );
std::thread t2 ( [ & q ]{ q.emplace_back( 2 ); } );
Run Code Online (Sandbox Code Playgroud)
编辑:为了进一步参考,这里是C++ 14标准(实际上,2014年11月的工作草案,N4296)关于deque引用和迭代器有效性的插入:
- 23.3.3.4 deque修饰符
(......)
- 效果:在双端队列中间的插入使所有迭代器和对双端队列元素的引用无效.在deque两端的插入使deque的所有迭代器无效,但对deque元素的引用的有效性没有影响.
(......)
在标准类的对象上同时调用任何两个方法是不安全的,除非两者都是const,或者除非另有说明(例如 的情况std::mutex::lock())。这是更详细的探讨here
因此,使用emplace_back和operator[]同时是不是安全的。但是,由于您引用的引用/指针有效性规则,您可以deque在调用emplace_back/ 的同时安全地使用先前获得的对元素的push_back引用,例如:
int main()
{
std::deque<int> d;
d.push_back(5);
auto &first = d[0];
auto task = std::async(std::launch::async, [&] { first=3; });
d.push_back(7);
task.wait();
for ( auto i : d )
std::cout << i << '\n';
}
Run Code Online (Sandbox Code Playgroud)
这将安全地输出 3 和 7。请注意,该引用first是在启动异步任务之前创建的。
| 归档时间: |
|
| 查看次数: |
1276 次 |
| 最近记录: |