c++ - 根据用户请求停止 tbb 线程

标签 c++ multithreading tbb

我的主线程正在进行更长的计算。在那段时间应该运行第二个线程(一种计算监视/统计)。一旦计算完成,它应该停止监视线程。使用了使用共享标志变量的经典方法(c.f. How to stop a running thread safely on user request?)。

#include <iostream>

#include "tbb/compat/thread"
#include "tbb/atomic.h"
#include "tbb/spin_mutex.h"

using namespace tbb;
using namespace std;


class Foo {
    bool _stop;
    spin_mutex _stopMutex;

public:
    Foo();
    void operator()();
    bool stop();
    void stop(bool);
};

Foo::Foo() {
    _stop = false;
}

bool Foo::stop() {
    spin_mutex::scoped_lock lock(_stopMutex);
    return _stop;
}

void Foo::stop(bool stop) {
    spin_mutex::scoped_lock lock(_stopMutex);
    _stop = stop;
    cout << "Foo::stop(bool) new value: " << _stop << endl;
}

void Foo::operator ()() {
    int i = 0;
    while (true) {
        cout << "   Foo::operator() still alive " << i << endl;
        {
            spin_mutex::scoped_lock lock(_stopMutex);
            if (_stop) {
                cout << "   Foo::operator() is asked to finish" << endl;
                break;
            }
        }
        if (i > 15) {
            spin_mutex::scoped_lock lock(_stopMutex);
            _stop = true;;
        }
        sleep(1);
        ++i;
    }
}

int main() {
    Foo foo;
    thread fooThread(foo);

    cout << "starting longer calculation" << endl;
    int sum;
    for (int i = 0; i < 3; ++i) {
        sum += i;
        sleep(1);
    }
    cout << "finished longer calculation" << endl;

    for (int i = 0; i < 5; ++i) {
        foo.stop(true);
        cout << "main() stop=" << foo.stop() << endl;
        sleep(1);
    }

    cout << "main() calling join()" << endl;
    fooThread.join();
    cout << "main() fooThread joined" << endl;

    return 0;
}

但是,共享变量不在线程之间共享。看起来每个线程都有自己的实例!监视线程在它自己停止之前不会停止。看看输出:

starting longer calculation
   Foo::operator() still alive 0
   Foo::operator() still alive 1
   Foo::operator() still alive 2
finished longer calculation
Foo::stop(bool) new value: 1
main() stop=1
   Foo::operator() still alive 3
Foo::stop(bool) new value: 1
main() stop=1
   Foo::operator() still alive 4
   Foo::operator() still alive 5
Foo::stop(bool) new value: 1
main() stop=1
   Foo::operator() still alive 6
Foo::stop(bool) new value: 1
main() stop=1
   Foo::operator() still alive 7
Foo::stop(bool) new value: 1
main() stop=1
   Foo::operator() still alive 8
main() calling join()
   Foo::operator() still alive 9
   Foo::operator() still alive 10
   Foo::operator() still alive 11
   Foo::operator() still alive 12
   Foo::operator() still alive 13
   Foo::operator() still alive 14
   Foo::operator() still alive 15
   Foo::operator() still alive 16
   Foo::operator() still alive 17
   Foo::operator() is asked to finish
main() fooThread joined

这是怎么回事?提前感谢您的回答!

最佳答案

David,感谢您提供的所有有用提示。如果您只需要坚持使用 tbb,那么引用共享数据的 Foo 构造函数就可以了。我使用 Boost 找到了一个更独立的解决方案。我的实际意图是这样的:

#include <iostream>

#include "boost/ref.hpp"
#include "boost/thread.hpp"

#include "tbb/atomic.h"

using namespace std;
using namespace tbb;

class Foo : public boost::thread {
    atomic<bool> _stop;

public:
    Foo();
    Foo(const Foo& rhs);
    void operator()();
    void stop();
};

Foo::Foo() : thread(ref(*this)) {
    cout << "Foo::Foo() called: " << this << endl;
    _stop = false;
}

Foo::Foo(const Foo& rhs) {
    cout << "Foo::Foo(const Foo&) called: " << this << endl;
    _stop = rhs._stop;
}

void Foo::stop() {
    _stop = true;
    cout << "Foo:stop() set _stop=" << _stop << endl;
    cout << "Foo:stop() calling interrupt()" << endl;
    interrupt();
    cout << "Foo:stop() calling join()" << endl;
    join();
    cout << "Foo:stop() joined" << endl;
}

void Foo::operator()() {
    int i = 0;
    while (!_stop) {
        cout << "   Foo::operator() still alive " << i << " (" << this << ")" << endl;
        if (_stop) {
            cout << "   Foo::operator() is asked to finish" << " (" << this << ")" << endl;
            break;
        }
        boost::this_thread::sleep( boost::posix_time::seconds(20) );
        ++i;
    }
}

int main() {
    Foo foo;

    cout << "starting longer calculation" << endl;
    int sum;
    for (int i = 0; i < 3; ++i) {
        sum += i;
        sleep(1);
    }
    cout << "finished longer calculation" << endl;

    foo.stop();

    return 0;
}

这导致

Foo::Foo() called: 0x7fff6c7b9ff0
starting longer calculation
   Foo::operator() still alive 0 (0x7fff6c7b9ff0)
finished longer calculation
Foo:stop() set _stop=1
Foo:stop() calling interrupt()
Foo:stop() calling join()
Foo:stop() joined

关于c++ - 根据用户请求停止 tbb 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12251778/

相关文章:

c++ - 使 C++ std::string 在指定字符处结束?

java - LongAccumulator 没有得到正确的结果

multithreading - 更新线程变量 (c++)

c# - HelloWorld 多线程 C# 应用程序

c++ - TBB 并发 vector 是否支持旧的 C 风格循环?

c++ - 如何将我的链表插入函数从 O(N) 更改为 O(1)

Windows 上的 C++ : Using DirectInput without a window?

c++ - 校验数字的递归函数

c++ - 使用 Intel TBB 用随机数填充数组

c++ - TBB 中的 TLS enumerable_thread_specific