我正在阅读Scott Meyers的书中有效现代C ++中的条件变量,下面是文本。
std::condition_variable cv
std::mutex m
T1 (detecting task)
...
cv.notify_one();
T2 (reacting task)
...
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk);
...
}
这里的作者提到如下
互斥锁用于控制对共享数据的访问,但它完全是 检测和反应任务可能不需要这样做 调解。例如,检测任务可能负责 初始化全局数据结构,然后将其转换为反应 任务使用。如果检测任务从不访问数据结构 在初始化之后,如果反应任务之前从未访问它 检测任务表明它已准备就绪,两个任务将保持不变 通过程序逻辑走出彼此的方式。没有必要 对于互斥体。
在上面的文字中,我很难理解
作者的意思是“两个任务将通过程序逻辑保持彼此”?
作者的意思是什么,不需要互斥?
答案 0 :(得分:2)
互斥用于解决竞争条件,例如:
当两个或多个线程可以访问共享数据并且他们尝试同时更改它时,会出现争用情况
在你的情况下不会发生,因为在你的结构上进行的操作将在不同的时间范围内完成,即:不会引起任何竞争条件。由于您不需要同时编写两个线程,因此您不需要互斥锁。
同时考虑到当你有&#34; check-then-act&#34; (例如&#34;检查&#34;如果值是X,那么&#34;行动&#34;做依赖于值为X的事情)并且另一个线程对&#34之间的值做某事;检查&#34;和&#34;行为&#34;。
答案 1 :(得分:2)
检测任务和响应任务都访问相同的数据,但程序逻辑保证它们不会同时访问该数据。因此,它们不需要互斥(或任何其他机制)来防止对数据的并发访问,因为通过其他方式阻止了这种并发访问。另一种方法是程序逻辑。
&#34;程序逻辑&#34;指程序的控制流程。我将稍微重新格式化代码:
Data shared_data;
std::condition_variable cv;
std::mutex m;
void detecting_task()
{
initialise(shared_data);
cv.notify_one();
}
void reacting_task()
{
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk);
}
process(shared_data);
}
即使detecting_task
和reacting_task
同时开始,您也可以看到他们无法同时对shared_data
采取行动。程序逻辑是detecting_task
仅在通知 cv
之前触及数据,而reacting_task
仅触及 {之后的数据 {1}}会收到通知。因此它们不可能重叠,因此不需要通过互斥锁来保护cv
。
答案 2 :(得分:1)
基本上,文本说:当两个线程不访问任何共享资源时,不需要同步对资源的访问。也就是说,如果每个线程只使用自己的数据结构而没有其他线程访问它们,则不需要通过互斥锁进行任何锁定 - 没有其他线程可以访问相应的资源。
鉴于上下文,它似乎是一个简单的消息传递系统,即使用互斥锁和条件变量的东西,它描述了所有必要的同步:“检测线程”注意到某些内容并通过消息发送通知将系统传递给“反应线程”。它们之间唯一共享的是消息传递对象。
答案 3 :(得分:0)
我也不完全理解引文。如果您不保护共享数据,则无需使用互斥锁进行内存访问。这可能意味着,检测任务不需要锁定互斥锁。
但是,condition_variable
需要一个互斥量才能工作。这是因为,至少一些底层操作系统实现需要一个互斥锁,例如pthreads
请参阅:Why do pthreads’ condition variable functions require a mutex?