C ++中的线程11

时间:2014-03-23 08:59:26

标签: c++ multithreading c++11

我正在将我的C ++技能更新为C ++ 11。我是线程,总是一个问题区域。考虑一下这个测试代码:

// threaded.h
class MyThreadedClass
{
public:
    MyThreadClass();
    bool StartThread();
    bool IsThreadDone();
    inline void WorkThread();

private:
    std::thread* workThread;
    atomic<bool> threadDone;
}

// threaded.cpp
MyThreadedClass::MyThreadedClass() {
    workThread = nullptr;
    threadDone.store(true);
}

bool MyThreadedClass::StartThread() {
    if (!threadDone.load()) { return false; }
    threadDone.store(false);
    workThread = new std::thread(&MyThreadedClass:WorkThread, this);
    workThread->detach();
    return true;
}

bool MyThreadedClass:IsThreadDone() {
    return threadDone.load();
}

inline void MyThreadedClass::WorkThread() {
    while (some_condition) { /*Do work*/ }
    threadDone.store(true);
}

// main.cpp
int main() {
    MyThreadedClass testInstance;
    testInstance.StartThread();
    for (int x = 0; x < 10; x++) {
        do {
            // This is sometimes true:
            if (testInstance.StartThread()) { return 1;}
        } while (!testInstance.IsThreadDone())
    }
    return 0;
}

我想看看这种类型代码的最坏情况,因此我在主要等待线程终止时不断地敲击它。有时会触发main中的故障情况。与许多线程问题一样,它不一致,因此不容易调试。

使用了threadDone变量,因为我在实际代码中访问了一个文件,并且不希望多个线程访问同一个文件。

深入了解我所缺少的内容或使用C ++ 11习惯用法重新设计此内容的方法。

3 个答案:

答案 0 :(得分:0)

我对C ++ 11并发性的最佳参考/学习书是:Anthony C++ Concurrency in Action: Practical Multithreading

答案 1 :(得分:0)

使用 std :: mutex 而不是 std :: atomic ,实现非常简单。

class MyThreadedClass
{
    std::mutex _mutex;
    std::unique_ptr<std::thread> _thread;
    bool _done{false};
public:
    MyThreadClass() = default;
    bool StartThread()
    {
        std::lock_guard<std::mutex> lock(_mutex);
        if (_thread || _done) return false;
        _thread = std::make_unique<std::thread>(&MyThreadedClass, this);
        return true;
    }
    bool IsThreadDone()
    {
        std::lock_guard<std::mutex> lock(_mutex);
        return _done;
    }
    void WorkThread()
    {
        // do some work
        std::lock_guard<std::mutex> lock(_mutex);
        _done = true;
    }
}

答案 2 :(得分:0)

您的main()函数中存在竞争条件(虽然不是&#34;数据竞赛&#34;),我已在下面转录,内联和简化:

void MyThreadedClass::WorkThread() {
    threadDone.store(true);
}

int main() {
    MyThreadedClass testInstance;
    testInstance.threadDone.store(false);
    new std::thread(&MyThreadedClass::WorkThread, &testInstance)->detach();
    // This sometimes fails:
    assert(!testInstance.threadDone.load());
    return 0;
}

如果在重新安排主线程之前WorkThread碰巧运行完成,那么断言将失败。由于标准不会限制调度,因此如果需要工作线程等待,则需要编写一些代码来阻止。