我在www.example.com上找到了条件变量http://en.cppreference.com/w/cpp/thread/condition_variable的以下示例www.cppreference.com。对cv.notify_one()的调用被放置在锁之外。我的问题是,是否应该在持有锁的同时进行调用,以确保等待线程实际上处于等待状态,并将接收通知信号。
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
void worker_thread()
{
// Wait until main() sends data
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return ready;});
// after the wait, we own the lock.
std::cout << "Worker thread is processing data\n";
data += " after processing";
// Send data back to main()
processed = true;
std::cout << "Worker thread signals data processing completed\n";
// Manual unlocking is done before notifying, to avoid waking up
// the waiting thread only to block again (see notify_one for details)
lk.unlock();
cv.notify_one();
}
int main()
{
std::thread worker(worker_thread);
data = "Example data";
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m);
ready = true;
std::cout << "main() signals data ready for processing\n";
}
cv.notify_one();
// wait for the worker
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return processed;});
}
std::cout << "Back in main(), data = " << data << '\n';
worker.join();
}
如果notify_one()调用被移动到锁内部以保证等待线程接收到通知信号,
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m);
ready = true;
cv.notify_one();
std::cout << "main() signals data ready for processing\n";
}
4条答案
按热度按时间hvvq6cgz1#
你不需要在锁的情况下通知,但是,由于通知在逻辑上是在实际值被更改时发生的(否则,为什么要通知?),而且更改必须在锁的情况下发生,所以它通常在锁内完成。
不会有实际可观察到的差异。
lyr7nygr2#
如果我没理解错你的问题的话,它等同于 “当通知程序线程试图通知其他线程中的某个CV时,是否应该锁定互斥锁”
不,这不是强制性的,甚至会产生一些反作用。
当从另一个线程通知
condition_variable
时,它试图重新锁定它在其上休眠的互斥体。从其工作线程锁定该互斥体将阻塞试图锁定它的另一个线程,直到该锁 Package 器超出范围。附言
如果您从发送数据到工作线程的函数中删除锁定,
ready
和processed
至少应该是原子的。当前它们由锁定同步,但是当您删除锁定时,它们不再是线程安全的wz1wpwve3#
在调用notify_all时保持锁是至关重要的:当condition_variable在等待之后被破坏时,虚假唤醒可导致等待结束,并且condition_variable在notify_all被调用于已被破坏的对象之前被破坏。
5sxhfpxr4#
如果不等待条件变量,则通知将丢失。您是否持有任何锁并不重要。条件变量是同步原语,不需要锁来保护。
锁和不锁都可能丢失信号。互斥锁只保护
ready
或processed
等普通数据。