2

我的主线程正在进行更长的计算。在此期间,应该运行第二个线程(计算监视/统计类型)。一旦计算完成,它应该停止监视线程。使用了使用共享标志变量的经典方法(参见如何根据用户请求安全地停止正在运行的线程?)。

#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

这里发生了什么?提前感谢您的回答!

4

1 回答 1

0

大卫,感谢您提供的所有有用提示。如果您只需要坚持使用 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
于 2012-09-04T09:30:48.540 回答