【问题标题】:C++ thread exit loop conditionC++线程退出循环条件
【发布时间】:2018-03-09 22:25:37
【问题描述】:

我想在线程中创建一个计数器,并通过更改布尔值来停止它。

这是我的代码:

#include <unistd.h>
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

using namespace std;

bool _terminateT;
mutex mtx;
condition_variable cv;

void counter()
{
    unique_lock<mutex> lock(mtx);
    int i(0);

    while(!_terminateT)
    {
        cout<<i<<endl;
        i++;
        cv.wait(lock);
    }
}

int main()
{
    _terminateT = false;
    thread t(counter);

    sleep(4);
    {
        lock_guard<mutex> lckg(mtx);
        _terminateT = true;
    }

    cv.notify_one();

    cout<<"main"<<endl;
    t.join();

    return 0;
}

问题是循环被wait 函数阻塞。 有没有办法在不阻塞while循环的情况下保护_terminateT变量?

【问题讨论】:

    标签: c++ linux multithreading loops condition-variable


    【解决方案1】:

    对于该代码,您不需要条件变量。保护布尔变量的互斥锁就足够了。它应该在循环检查中被锁定和解锁。

    事实上,在没有数据竞争风险的特定示例中(您只需将变量从 0 设置为其他值一次),您甚至可以跳过互斥锁并以不受保护的方式设置变量 - 循环将始终终止,因为即使线程运行在除 main 函数之外的其他内核上,它的缓存最终也会得到正确的更改值。如果您在线程之间共享其他数据,情况会有所不同。

    【讨论】:

    • 非常感谢您的快速回复!但是,如果我在循环检查变量的值时更改了变量的值会发生什么?变量不会同时被读取和设置吗?
    • 这是不可能的。从这个角度来看,处理器以原子方式工作,并且(过于简单化!)他们当时只做一件事。如果情况不同并且您的变量不是将 0 更改为非 0,例如将 0000000000000000 更改为 123456789ABCDF01,则当一个 CPU 内核正在写入而另一个 CPU 内核正在读取时,可能会发生数据竞争。这可能会导致读者看到值为 1234567800000000 - 所以更新了一半。您可以阅读有关“缓存一致性”和 MESI 的信息,但这很复杂 :) 但是处理器不会“中断”,只是读取器线程读取虚假数据。
    • 非常感谢您的澄清!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 1970-01-01
    • 2014-09-08
    • 2018-03-11
    • 2012-03-01
    相关资源
    最近更新 更多