c ++ 11个线程:无法停止线程

时间:2017-06-30 07:22:11

标签: multithreading c++11

我正在学习在c ++ 11中使用线程(我主要通过某些框架使用线程,但不是直接使用线程)。

这是一个在新线程中运行run()方法的简单类。 start() / stop()方法用于控制线程生命周期:

#include <thread>
#include <mutex>
#include <iostream>
#include <memory>
#include <atomic>
#include <unistd.h>

using namespace std;

class ThreadTest
{
public:
    ThreadTest() : _run(false), _t(nullptr) {}
    void start()
    {   
        lock_guard<mutex> g(_mutex);
        cout << "Starting new thread..." << endl;
        _run = true;
        if (!_t) {
            _t.reset(new thread(&ThreadTest::run, this));
        }
    }

    void stop()
    {   
        lock_guard<mutex> g(_mutex); 
        cout << "Stopping thread..." << endl;
        _run = false;
        if (_t) {
            _t->join();
            _t.reset(nullptr);
        }
    }

    void run()
    {   
        while(true) {
            lock_guard<mutex> g(_mutex);
            if (!_run) {
                return;
            }
            cout << "Running every sec" << endl;
            sleep(1);
        } 
   }

private:
    atomic<bool> _run;
    unique_ptr<thread> _t;
    mutex _mutex;
};

int main()
{
    ThreadTest t;
    t.start();
    cout << "Sleeping for 2 secs..." << endl;
    sleep(2);
    cout << "Done" << endl;
    t.stop();
    return 0;
}

示例输出:

Starting new thread...
Sleeping for 2 secs...
Running every sec
Running every sec
Done
Running every sec
Running every sec
Running every sec
Running every sec

问题是线程在调用stop() NOT 停止了!在调试时,我发现它卡在此函数中试图获取锁_mutex,因此_run变量尚未设置为false。我知道,因为_run是一个atomic,我在这里并不严格需要锁,但我试图在这里理解锁的用法。

while run()循环再次循环时,是否应该获取互斥锁?

对于我的生活,我无法解释这个微不足道的问题! :/

1 个答案:

答案 0 :(得分:0)

我发现了这个错误。

stop()函数中,我应该限制锁定持续时间的范围:

void stop()
{   
    {
    lock_guard<mutex> g(_mutex); 
    _run = false;
    }
    if (_t) {
        _t->join();
        _t.reset(nullptr);
    }
}

而且在run()函数的主循环中,我应该在检查_run的值时(而不是在sleep时)保持锁定

void run()
{   
    while(true) {
        {
            lock_guard<mutex> g(_mutex);
            if (!_run) {
                return;
            }
        }
        cout << "Running every sec" << endl;
        sleep(1);
    }
}