C++线程竞争条件模拟

ane*_*kix 3 c++ multithreading mutex

这是一个C++程序,它运行10时间与5不同的线程,每个线程递增value,counter所以最终输出应该是500,这正是程序提供输出.但我不明白为什么500每次输出都应该不同,因为增量操作不是atomic,并且没有使用锁,所以程序应该在每种情况下给出不同的输出.

编辑以增加竞争条件的概率我增加了循环计数但仍然看不到任何变化的输出

#include <iostream>
#include <thread>
#include <vector>

struct Counter {
    int value;

    Counter() : value(0){}

    void increment(){
        value = value + 1000;
    }
};

int main(){
    int n = 50000;
    while(n--){
    Counter counter;

    std::vector<std::thread> threads;
    for(int i = 0; i < 5; ++i){
        threads.push_back(std::thread([&counter](){
            for(int i = 0; i < 1000; ++i){
                counter.increment();
            }
        }));
    }

    for(auto& thread : threads){
        thread.join();
    }

    std::cout << counter.value << std::endl;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Ant*_*hev 5

你真幸运:)

用clang ++编译我的输出并不总是500:

500
425
470
500
500
500
500
500
432
440
Run Code Online (Sandbox Code Playgroud)


小智 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)
Run Code Online (Sandbox Code Playgroud)

显示竞争状况.(另外,在我的系统上,输出显示的结果不同于500).

g ++的选项在g ++的文档中解释(例如:man g ++).另请参阅:https://github.com/google/sanitizers/wiki#threadsanitizer.