Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading C++;11原子容器的螺纹安全_Multithreading_C++11_Containers_Atomic_Atomicity - Fatal编程技术网

Multithreading C++;11原子容器的螺纹安全

Multithreading C++;11原子容器的螺纹安全,multithreading,c++11,containers,atomic,atomicity,Multithreading,C++11,Containers,Atomic,Atomicity,我正在尝试实现一个没有互斥锁的线程安全STL向量。因此,我完成了post并为原子原语实现了一个包装器 然而,当我运行下面的代码时,它显示出失败两次(只有两个争用条件实例),因此它似乎不是线程安全的。我想知道我怎样才能解决这个问题 包装类 模板 结构原子变量 { std::原子; 原子变量():原子(T()){} 显式原子变量(T const&v):原子(v){} 显式原子变量(std::atomicconst&a):原子变量(a.load()){} 原子变量(原子变量常量和其他): 原子(oth

我正在尝试实现一个没有互斥锁的线程安全STL向量。因此,我完成了post并为原子原语实现了一个包装器

然而,当我运行下面的代码时,它显示出
失败两次(只有两个争用条件实例),因此它似乎不是线程安全的。我想知道我怎样才能解决这个问题

包装类

模板
结构原子变量
{
std::原子;
原子变量():原子(T()){}
显式原子变量(T const&v):原子(v){}
显式原子变量(std::atomicconst&a):原子变量(a.load()){}
原子变量(原子变量常量和其他):
原子(other.atomic.load()){}
内联原子变量和运算符=(原子变量常量和rhs){
atomic.store(rhs.atomic.load());
归还*这个;
}
内联原子变量和运算符+=(原子变量常量和rhs){
atomic.store(rhs.atomic.load()+atomic.load());
归还*这个;
}
内联布尔运算符!=(原子变量常量和rhs){
return!(atomic.load()==rhs.atomic.load());
}
};
typedef原子变量AtomicInt;
功能和测试

//100个元素的向量。
向量公共(100,原子数(0));
void add10(向量和参数){
for(vector::iterator it=param.begin();
it!=param.end();++it){
*it+=AtomicInt(10);
}
}
void add100(向量和参数){
for(vector::iterator it=param.begin();
it!=param.end();++it){
*it+=AtomicInt(100);
}
}
void doParallelProcessing(){
//创建线程
标准::线程t1(添加10,标准::参考(通用));
标准::螺纹t2(add100,标准::参考(通用));
//加入他们
t1.join();
t2.连接();
//再次打印矢量
for(vector::iterator it=common.begin();
it!=common.end();++it){
if(*it!=AtomicInt(110)){
请注意

           atomic.store(rhs.atomic.load() + atomic.load());
不是原子的

你有两个选择来解决它。 回忆录 1) 使用互斥锁

编辑正如注释中提到的T.C,这是不相关的,因为这里的操作将是load()然后load()然后store()(非松弛模式)-因此内存顺序在这里不相关

2) 使用内存顺序

memory_order_acquire:保证后续加载不会在当前加载或任何先前加载之前移动。 内存\u顺序\u释放:前面的存储不会移过当前存储或任何后续存储


我仍然不确定2,但我认为如果存储不是并行的,它会工作。

只需将运算符+=写为:

    inline AtomicVariable& operator+=(AtomicVariable const &rhs) {
        atomic += rhs.atomic;
        return *this;
    }
在文档中:运算符+=是原子的

您的示例失败,因为以下执行场景是可能的:

  • Thread1-rhs.atomic.load()-返回10;Thread2-rhs.atomic.load()-返回100
  • Thread1-atomic.load()-返回0;Thread2-atomic.load-返回0
  • 线程1-添加值(0+10=10);线程2-添加值(0+100)
  • Thread1-atomic.store(10);Thread2-atomic.store(100)

  • 最后,在这种情况下,原子值可能是10或100,这取决于哪个线程首先执行atomic.store。

    您的
    AtomicVariable
    不仅仅是毫无意义的-它是积极有害的。它使用
    std::atomic
    ,并使其某些操作非原子化。特别是,
    std::atomic::operator+=
    是原子的,而ode>AtomicInt::operator+=
    不是。这没有任何意义。是的,您显示了两条指令,但每一条指令都会触及其各自单独的内存位置。对于“非原子”的内容,应该对同一内存位置进行两次读取和/或修改。真正的问题在于
    operator+=
    atomic.store(rhs.atomic.load())+atomic.load())
    这在同一个原子上调用
    load
    store
    。@igortandtnik-这两条指令是问题所在。如果顺序是T1 load T2 load T2 store T1 load,则会出现问题,因为它们触及相同的内存。我不理解您的表示法。在任何情况下,您的示例都会从一块内存加载并存储到另一块内存;而y不要“触摸相同的记忆”是的,
    +=
    不是原子的。但是你似乎把
    操作符=
    ,而不是
    操作符+=
    ,作为罪魁祸首-而且我看不出
    操作符=
    有任何错误。事实上,
    标准::原子::操作符=
    做的正是相同的事情。关于内存顺序的模糊手工操作是无用的,也是错误的。通过诽谤t
    std::atomic
    已经使用了最强的内存顺序(
    memory\u order\u seq\u cst
    )。或者,就此而言,只需删除
    AtomicVariable
    并直接使用
    std::atomic
    。包装器似乎完全没有意义。现在就查看一下。@IgorTandetnik它是必需的,因为运算符没有隐式转换。可能是我编码错误,但我尝试过使用std::atomic,但它没有编译。@JohnJohn让
    AtomicVariable::operator+=
    调用底层的
    atomic::operator+=
    。如
    atomic+=rhs.atomic.load()
    。或
    atomic.fecth\u add(rhs.atomic.load())
    。这应该会有所帮助。请阅读位于的文档,我不知道,感谢您指出这一点。