从 C++11 中的另一个线程解锁一个线程

Unlock a thread from another thread in C++11

我在 C++11 的 thread.h api 方面的知识并不广泛(事实上我也不熟悉线程编程,但我最近读到了它很多并且了解并发性和类似的东西)但是我开始使用它并且我遇到了一个我从未真正遇到过的问题。

我有两个线程函数,说这些

std::thread(thread1, args); // Spawn thread 1
std::thread(thread2, args); // Spawn thread 2

[...]

int thread1(bunch of args)
{
     lock_thread_2();
     [do stuff]
     while (some condition) {
         [do stuff]
         unlock_thread_2();
     }
}

int thread2(bunch of args)
{
     while (some condition) {
         [do stuff]
         wait_for_thread1_to_unlock_me();
     }
}

我首先想到用 std::mutex 来做,但我读到它可能很危险,因为如果我解锁一个已经解锁的互斥体,行为是未定义的,并且在它之上它无论如何都不会工作,因为mutex.lock() 不一定会暂停执行(只有当互斥体已经被锁定时才会暂停)所以写起来会非常可怕,我必须将 unlock() 和 lock() 调用结合在一起.

这里需要注意的是,thread2 的执行仅由thread1 控制,但thread2 永远不会以任何方式锁定thread1。只有thread2被thread1加锁,只有thread1控制thread2的执行流程,否则不会。

您将如何以干净、受支持的方式做到这一点?能否给个代码示例?

谢谢!

使用 condition_variable:

std::condition_variable cv;

int thread1(bunch of args)
{
     [do stuff]
     while (some condition) {
         [do stuff]
         cv.notify_one();
     }
}

int thread2(bunch of args)
{
     std::mutex mtx;
     std::unique_lock<std::mutex> lk(mtx);

     while (some condition) {
         [do stuff]
         cv.wait(lk);
     }
}

wait() returns 时,cv 将被 notify() 编辑...或者将出现虚假唤醒。为了处理后者,添加谓词通常很有帮助。

您可以使用 std::condition_variable。它允许您通过使用 notify_onenotify_all 方法从另一个线程通知一个线程,以分别恢复一个或所有等待条件变量的线程。在您的代码中,您可以像这样使用它:

std::condition_variable my_var;

void thread1(args) {
    ...
    while(condition1) {
        ...
        my_var.notify_one();
    }
}

void thread2(args) {
    std::mutex mutex;
    std::unique_lock<std::mutex> lock(mutex);
    ...
    while(condition2) {
        ...
        my_var.wait(lock);
    }
}

不过要小心,条件变量偶尔会受到虚假唤醒的影响,因此您可能希望循环等待条件以检查唤醒是否有效,如下所示:

do {
    my_var.wait(lock);
} while(!valid_wakeup);

您可以阅读更多关于 std::condition_variable here