从 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的执行流程,否则不会。
您将如何以干净、受支持的方式做到这一点?能否给个代码示例?
谢谢!
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_one
或 notify_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。
我在 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的执行流程,否则不会。
您将如何以干净、受支持的方式做到这一点?能否给个代码示例?
谢谢!
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_one
或 notify_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。