C ++线程未检测到全局变量更改

我有2个线程监视同一全局state,如果state.shutdown变成false,则线程run()应该返回。代码如下。

#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>

using namespace std;

struct State {
    bool shutdown = false;

    ~State() {
        shutdown = true;
    }
};

State state;

#define CHECK_SHUTDOWN     \
  {                        \
    std::cout << (state.shutdown ? " SHUTDOWN " : " NOSHUT ") << typeid(*this).name() << std::endl; \
    if (state.shutdown) {  \
        return;            \
    }                      \
  }

class Mythread {
public:
    void join();
    void run();
    void launch();
    std::thread self_thread;
};

void Mythread::run() {
    while(1) {
        CHECK_SHUTDOWN
    }
}

void Mythread::join() {
    if (self_thread.joinable()) {
        self_thread.join();
    }
}

void Mythread::launch() {
    self_thread = std::thread(&Mythread::run,this);
}

std::mutex mtx;
void shut() {
    std::lock_guard<std::mutex> lock(mtx);   
    state.shutdown = true;
}

int main()
{
    Mythread thread1;
    Mythread thread2;

    thread1.launch();
    thread2.launch();

    std::this_thread::sleep_for(std::chrono::milliseconds(1000));


    //state.shutdown = true;
    shut(); //This makes no difference with the line above

    std::this_thread::sleep_for(std::chrono::milliseconds(100));

    thread1.join();
    thread2.join();


    return 0;
}

但是,即使我手动将state.shutdown设置为true,线程也永远无法检测到它。我有类似的照片:

 NOSHUT 8Mythread                                                                                                
 NOSHUT 8Mythread                                                                                                
 NOSHUT 8Mythread                                                                                                                                                                                                                

...Program finished with exit code 0                                                                             
Press ENTER to exit console. 

最后。鉴于永不返回run()函数,线程连接应该挂起,我也感到困惑。但是,线程可以成功加入。

任何帮助在这里都将不胜感激!

iCMS 回答:C ++线程未检测到全局变量更改

关闭时您有data race

当一个表达式的评估值写入一个存储位置,而另一个评估值读取或修改了相同的存储器位置时,这些表达式就会发生冲突。具有两个冲突评估的程序具有数据竞争[...]

shut()中,您使用互斥锁设置了shutdown标志,但在没有互斥锁的情况下执行了 检查(State析构函数未使用互斥体)。因此,您对非原子变量的操作(读+写)有冲突,没有在关联之前进行正确的操作。这是导致不明确行为的数据竞赛。

简单的解决方案是将shutdown设为std::atomic<bool>,那么您甚至不需要互斥体来设置标志。

有关数据竞争和C ++内存模型的更多详细信息,我可以推荐我与他人合着的这篇论文:Memory Models for C/C++ Programmers

本文链接:https://www.f2er.com/2248638.html

大家都在问