这是一个C ++程序,运行10
次5
个不同的线程,每个线程递增value
counter
,因此最终输出应为{{1} },这正是程序提供输出的内容。但我不明白为什么每次输出应该不同时给出500
,因为增量操作不是500
并且没有使用锁,所以程序应该在每种情况下给出不同的输出。 / p>
编辑以增加竞争条件的概率我增加了循环计数但仍然看不到任何变化的输出
atomic
答案 0 :(得分:5)
你很幸运:)
使用clang ++进行编译我的输出并不总是500:
500
425
470
500
500
500
500
500
432
440
答案 1 :(得分:5)
注意强>
使用g ++和-fsanitize = thread -static-libtsan:
WARNING: ThreadSanitizer: data race (pid=13871)
Read of size 4 at 0x7ffd1037a9c0 by thread T2:
#0 Counter::increment() <null> (Test+0x000000509c02)
#1 main::{lambda()#1}::operator()() const <null> (Test+0x000000507ed1)
#2 _M_invoke<> /usr/include/c++/5/functional:1531 (Test+0x0000005097d7)
#3 operator() /usr/include/c++/5/functional:1520 (Test+0x0000005096b2)
#4 _M_run /usr/include/c++/5/thread:115 (Test+0x0000005095ea)
#5 <null> <null> (libstdc++.so.6+0x0000000b8c7f)
Previous write of size 4 at 0x7ffd1037a9c0 by thread T1:
#0 Counter::increment() <null> (Test+0x000000509c17)
#1 main::{lambda()#1}::operator()() const <null> (Test+0x000000507ed1)
#2 _M_invoke<> /usr/include/c++/5/functional:1531 (Test+0x0000005097d7)
#3 operator() /usr/include/c++/5/functional:1520 (Test+0x0000005096b2)
#4 _M_run /usr/include/c++/5/thread:115 (Test+0x0000005095ea)
#5 <null> <null> (libstdc++.so.6+0x0000000b8c7f)
显示竞争条件。 (另外,在我的系统上,输出显示的结果不同于500)。
g ++的选项在g ++的文档中解释(例如:man g ++)。另见:https://github.com/google/sanitizers/wiki#threadsanitizer。
答案 2 :(得分:4)
仅仅因为您的代码具有竞争条件并不意味着它们会发生。这是他们的难点。很多时候,只有在其他事情发生变化且时间不同时才会出现这种情况。
这里有几个问题:递增到100可以非常快。因此,在第二个线程启动之前,您的线程可能已经完成了一半。对于下一个线程等也是如此。所以你永远不会知道你真的有5个并行。
您应该在每个帖子的开头创建一个屏障,以确保它们同时启动。
也许可以尝试比#34; 100&#34;并且只有5个线程。但这一切都取决于系统/负载/时间。等
答案 3 :(得分:1)
增加竞争条件的概率我增加了循环次数 但仍然看不到任何变化的输出
严格地说,您在此代码中有数据争用,这是未定义的行为,因此您无法可靠地重现它。
但您可以在Counter
中将increment
重写为某些具有人为延迟的“等效”代码:
struct Counter {
int value;
Counter() : value(0){}
void increment(){
int val=value;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
++val;
value=val;
}
};
我用这个计数器得到了以下输出,远远低于500
:
100
100
100
100
100
101
100
100
101
100