gpt4 book ai didi

c++ - std::thread::join 在析构函数中挂起

转载 作者:太空狗 更新时间:2023-10-29 21:44:30 25 4
gpt4 key购买 nike

我有以下代码在专用线程上运行函数。除了析构函数,它工作得很好。对 thread_.join() 的调用没有返回。我正在使用 VS2013 Express。

我要更改什么才能使线程正确连接?

#include <atomic>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <vector>

namespace
{
class main_thread
{
public:
static auto instance() -> main_thread&
{
static main_thread instance_;
return instance_;
}
auto enque(std::function<void()> func) -> void
{
{
std::lock_guard<std::mutex> lock{ mutex_ };
queue_.push_back(func);
}
condition_.notify_one();
}
private:
main_thread()
{
continue_.test_and_set();
thread_ = std::thread{ std::bind(std::mem_fn(&main_thread::run), this) };
}
~main_thread()
{
continue_.clear();
condition_.notify_all();
if (thread_.joinable())
{
thread_.join();
}
}
main_thread(const main_thread &other) = delete;
main_thread(main_thread &&other) = delete;
main_thread& operator=(const main_thread &other) = delete;
main_thread& operator=(main_thread &&other) = delete;

auto run() -> void
{
while (continue_.test_and_set())
{
auto lock = std::unique_lock<std::mutex>{ mutex_ };
//condition_.wait_for(lock, std::chrono::milliseconds(1));
condition_.wait(lock);
for (auto &func : queue_)
{
func();
}
queue_.clear();
}
}

std::condition_variable condition_;
std::mutex mutex_;
std::vector<std::function<void()>> queue_;
std::thread thread_;
std::atomic_flag continue_;
};
}

auto on_main_thread(std::function<void()> func) -> void
{
main_thread::instance().enque(std::move(func));
}

auto on_main_thread_sync(std::function<void()> func) -> void
{
bool done{ false };
on_main_thread([&]{
func();
done = true;
});
while (!done);
}

执行这段代码的唯一函数是

int main()
{
on_main_thread([]{});
}

这避免了 on_main_thread_sync 中的竞争问题,但仍然有 ~main_thread 中的锁定。 Visual Studio 指示有 2 个线程,但 main_thread::run 中都没有,所以我不明白发生了什么。该函数正确退出,但由于某种原因线程没有结束。

最佳答案

你不应该在代码的关键部分调用外部代码,这很容易导致死锁。

如果您在调试器中暂停执行,您可能会看到有一个或多个线程在等待获取 _mutex。

如果从 func() 调用的任何代码尝试 enqueue(),您将无法再次获取 _mutex 上的 unique_lock

condition_variable 等待结束后尝试释放锁。作为测试,您可以放入一个额外的范围以查看这是否有帮助:

while (continue_.test_and_set())
{
std::vector<std::function<void()>> queue;
{
auto lock = std::unique_lock<std::mutex>{ mutex_ };
//condition_.wait_for(lock, std::chrono::milliseconds(1));
condition_.wait(lock);
queue.swap(queue_);
}
for (auto &func : queue)
{
func();
}
}

关于c++ - std::thread::join 在析构函数中挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19968512/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com