Vio*_*ffe 5 c++ windows multithreading c++11 visual-studio-2015
考虑以下代码。以下所有内容均使用 v140 C++ 运行时在 Visual Studio 2015 中编译和执行:
#include <thread>
#include <atomic>
#include <sstream>
#include <Windows.h>
struct StaticThreadTest
{
~StaticThreadTest()
{
_terminationRequested = true;
if (_thread.joinable())
_thread.join();
std::ostringstream ss;
ss << "Thread finished gracefully: " << _threadFinishedGracefully << "\n";
OutputDebugStringA(ss.str().c_str());
}
void startThread()
{
_thread = std::thread([&]() {
while (!_terminationRequested);
_threadFinishedGracefully = true;
});
}
std::thread _thread;
std::atomic<bool> _terminationRequested {false};
std::atomic<bool> _threadFinishedGracefully {false};
};
static StaticThreadTest thread;
int main()
{
thread.startThread();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它按预期工作 - 打印“线程正常完成:1”并且应用程序退出。
但是,如果我将此代码移至 DLL(创建一个空 DLL,从中导出一个函数,将该对象放置StaticThreadTest在 dll 的 .cpp 中,thread.startThread()从导出的函数调用并从 调用此导出的函数main.cpp),代码有时会打印“Thread优雅地完成:0”,但更多时候它只是挂在thread.join().
这种行为有记录吗?这是运行时的错误还是有意为之?
main.cpp值得注意的是:使用 v120 工具集编译的相同代码即使在(在 exe 中)也会 100% 挂起。似乎 v120 工具集中存在一个错误,而在 v140 中,它针对 .exe 进行了修复,但针对 .dll 进行了修复。
似乎使用不同的同步机制而不是繁忙循环(std::mutex+ std::condition_variable)可以消除这个问题。
以下示例演示了这两种机制:
#include "thread-test-dll.h"
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
//#define _BUSY_WAIT
#ifdef _BUSY_WAIT
#include <atomic>
#endif
class foo
{
public:
foo()
#ifdef _BUSY_WAIT
: termination_requested_(false),
terminated_gracefully_(false)
#endif
{
std::cout << "foo::foo()...\n";
}
void run()
{
#define _USE_LAMBDA
#ifdef _USE_LAMBDA
thread_ = std::thread([&]() {
work();
});
#else
thread_ = std::thread(&foo::work, this);
#endif
}
~foo()
{
std::cout << "foo::~foo()...\n";
if (thread_.joinable())
{
#ifdef _BUSY_WAIT
termination_requested_ = true;
#else
condition_variable_.notify_all();
#endif
thread_.join();
std::cout << "thread joined...\n";
}
else
{
std::cout << "thread was not joinable...\n";
}
#ifdef _BUSY_WAIT
std::cout << "terminated_gracefully_ = " << terminated_gracefully_ << "\n";
#endif
}
void work()
{
#ifdef _BUSY_WAIT
while (!termination_requested_);
terminated_gracefully_ = true;
#else
std::unique_lock<std::mutex> mutex_lock(mutex_);
condition_variable_.wait(mutex_lock);
#endif
std::cout << "foo:work() terminating...\n";
}
private:
#ifdef _BUSY_WAIT
std::atomic<bool> termination_requested_;
std::atomic<bool> terminated_gracefully_;
#endif
std::thread thread_;
std::mutex mutex_;
std::condition_variable condition_variable_;
};
static foo instance;
void runThread()
{
instance.run();
}
Run Code Online (Sandbox Code Playgroud)
但我仍然会研究是否可以让它挂起,std::atomic因为如果这是原因,那么它仍然是一个与退出std::thread::join()后调用的问题不同的问题。main
| 归档时间: |
|
| 查看次数: |
574 次 |
| 最近记录: |