在 DLL_DETACHED 上通知分离的线程

Notify Detached Thread on DLL_DETACHED

我有以下代码创建一组线程并立即分离它们:

#include <mutex>
#include <thread>
#include <queue>
#include <atomic>
#include <functional>

class TGroup final
{
private:
    std::mutex mutex;
    std::condition_variable condition;
    std::queue<std::function<void()>> tasks;
    std::atomic_bool stop;

public:
    TGroup();
    ~TGroup();
    TGroup(const TGroup&) = delete;
    TGroup& operator = (const TGroup&) = delete;

    void terminate();
    void execute(std::function<void()> &&task);
};

TGroup::TGroup() : mutex(), condition(), tasks(), stop(false)
{
    for (std::size_t i = 0; i < std::thread::hardware_concurrency(); ++i)
    {
        std::thread([this] {
            while(true)
            {
                std::unique_lock<std::mutex> lock(this->mutex);
                condition.wait(lock, [this] {
                    return !this->tasks.empty() || this->stop;
                });

                if (this->stop)
                {
                    lock.unlock();
                    break;
                }

                auto task = std::move(this->tasks.front());
                this->tasks.pop();
                lock.unlock();

                task();
            }
        }).detach();
    }
}

TGroup::~TGroup()
{
    this->terminate();
}

void TGroup::terminate()
{
    if (!this->stop)
    {
        std::unique_lock<std::mutex> lock(this->mutex);
        this->stop = true;
        lock.unlock();
        this->condition.notify_all();  //Causes a crash on Windows but not MacOS or Linux..
    }
}

void TGroup::execute(std::function<void()> &&task)
{
    if (!this->stop)
    {
        std::unique_lock<std::mutex> lock(this->mutex);
        this->tasks.emplace(task);
        lock.unlock();
        this->condition.notify_one();
    }
}

在我的DLL_DETACHED里面DLLMain,我调用group.terminate()。如果我在 TGroup.terminate().

中注释掉 this->condition.notify_all();,它工作得很好

通知条件变量会导致死锁的原因是什么?它目前导致我的进程在我按下退出按钮时不退出(我必须使用 TaskManager 来终止它)。

有什么想法吗?

您的程序包含 *this 上的数据争用,在 TGroup 对象被销毁与唤醒的线程试图访问 this->tasks 和其他成员变量之间。因此它表现出未定义的行为。

当您不调用 notify_all() 时,您允许操作系统在正常进程关闭过程中终止休眠线程。