gpt4 book ai didi

c++ - 在 condition_variable::notify_all() 之后或之前解锁互斥量?

转载 作者:搜寻专家 更新时间:2023-10-31 02:05:05 33 4
gpt4 key购买 nike

查看several videosdocumentation example ,我们在 调用 notify_all() 之前解锁互斥量。在之后调用它会更好吗?

常用方式:

Notifier 线程内:

//prepare data for several worker-threads;

//and now, awaken the threads:
std::unique_lock<std::mutex> lock2(sharedMutex);
_threadsCanAwaken = true;

lock2.unlock();
_conditionVar.notify_all(); //awaken all the worker threads;

//wait until all threads completed;

//cleanup:
_threadsCanAwaken = false;

//prepare new batches once again, etc, etc

在其中一个工作线程中:

while(true){
// wait for the next batch:

std::unique_lock<std::mutex> lock1(sharedMutex);
_conditionVar.wait(lock1, [](){return _threadsCanAwaken});
lock1.unlock(); //let sibling worker-threads work on their part as well

//perform the final task

//signal the notifier that one more thread has completed;

//loop back and wait until the next task
}

注意 lock2 在我们通知条件变量之前是如何解锁的——我们是否应该在 notify_all() 之后解锁它?

编辑

来 self 下面的评论:我担心的是,如果工作人员虚假地醒来,看到互斥量已解锁,超快地完成任务并循环回到 while 的开始,该怎么办。现在慢戳通知程序最终调用了 notify_all(),导致 worker 循环了额外的时间(过多且不受欢迎)。

最佳答案

除非您的实现不寻常,否则在向条件变量发出信号之前解锁互斥锁没有任何优势。先解锁再发信号有两个缺点:

  1. 如果您在发出信号之前解锁,信号可能会唤醒一个线程,该线程会在您解锁后选择阻塞条件变量。如果您使用相同的条件变量来指示多个逻辑条件,这可能会导致死锁。这种错误很难创建、难以诊断和理解。通过在解锁前始终发出信号可以轻松避免这种情况。这确保了共享状态和信号的更改是原子操作,并且竞争条件和死锁是不可能的。

  2. 在发信号之前解锁会降低性能,而在发信号之后解锁可以避免这种性能损失。如果你在解锁之前发出信号,一个好的实现会知道你的信号不可能使任何线程准备好运行,因为互斥锁由调用线程持有,并且任何受条件变量影响的线程在没有互斥锁的情况下必然无法向前推进.这允许进行显着的优化(通常称为“等待变形”),如果您先解锁,这是不可能的。

所以除非你有一些不寻常的理由不这样做,否则请在持有锁的同时发出信号。

关于c++ - 在 condition_variable::notify_all() 之后或之前解锁互斥量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52503361/

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