Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 需要对条件变量所寻求的(原子)分配进行互斥保护吗?_C++_Multithreading_Boost Thread - Fatal编程技术网

C++ 需要对条件变量所寻求的(原子)分配进行互斥保护吗?

C++ 需要对条件变量所寻求的(原子)分配进行互斥保护吗?,c++,multithreading,boost-thread,C++,Multithreading,Boost Thread,我了解如何使用条件变量(这个构造的简写名称IMO,因为cv对象既不是变量也不表示条件)。我有一对线程,用Boost.Thread设置为: bool awake = false; boost::mutex sync; boost::condition_variable cv; void thread1() { boost::unique_lock<boost::mutex> lock1(sync); while (!awake) cv.wait(lock

我了解如何使用条件变量(这个构造的简写名称IMO,因为cv对象既不是变量也不表示条件)。我有一对线程,用Boost.Thread设置为:

bool awake = false;
boost::mutex sync;
boost::condition_variable cv;
void thread1()
{
    boost::unique_lock<boost::mutex> lock1(sync);
    while (!awake)
        cv.wait(lock1);
    lock1.unlock();    // this line actually not canonical, but why not?
    // proceed...
}
void thread2()
{
    //...
    boost::unique_lock<boost::mutex> lock2;
    awake = true;
    lock2.unlock();
    cv.notify_all();
}
bool awake=false;
互斥同步;
boost::条件变量cv;
void thread1()
{
boost::唯一锁定锁1(同步);
当(!醒着)
cv.等待(锁1);
lock1.unlock();//这行实际上不是规范的,但为什么不是呢?
//继续。。。
}
无效线程2()
{
//...
boost::独特的锁2;
清醒=正确;
锁2.解锁();
cv.通知所有人();
}
我的问题是:thread2真的需要保护对
唤醒的分配吗?在我看来,
notify_all()
调用应该足够了。如果操作和检查的数据不仅仅是一个简单的“ok to Procedue”标志,我可以在互斥锁中看到值,但在这里它看起来有点过头了

第二个问题是代码片段中提出的:为什么Boost文档没有显示thread1中的锁在“process data”步骤之前被解锁

编辑:也许我的问题是:有没有比简历更干净的结构来实现这种等待

thread2真的需要保护任务才能唤醒吗

对。从一个线程修改一个对象并从另一个线程访问它而不进行同步会产生未定义的行为。即使它只是一个
bool

例如,在一些多处理器系统上,写操作可能只影响本地内存;如果没有显式的同步操作,其他线程可能永远看不到更改

为什么Boost文档没有显示thread1中的锁在“流程数据”步骤之前被解锁

如果在清除标志之前解锁互斥锁,则可能会错过另一个信号

有没有比CV更干净的结构来实现这种等待

升压和标准C++库中,没有;条件变量足够灵活,可以处理任意共享状态,并且对于这个简单的情况来说并不特别复杂,所以不需要特别简单


更一般地说,您可以使用信号量或管道在线程之间发送简单信号。

正式地说,您肯定需要两个线程中的锁:如果有线程的话 修改一个对象,多个线程访问它,然后 访问必须同步

在实践中,你很可能不用锁就能逃脱;它是 几乎可以肯定的是,
notify_all
将发布必要的围栏或 membar指令,以确保内存正确同步。 但为什么要冒险呢

至于
解锁的缺失
,这就是作用域的全部意义 锁定模式:
unlock
位于对象的析构函数中,因此
即使异常通过,互斥锁也将被解锁

是记忆同步的问题一直让我困惑。关于最后一点:信号量(这个名字)不是Boost或C++11线程的一部分;Boost.InterProcess有一个。现在还不清楚如何更简单。类似地,我不会用管道来处理单个进程。@ Mike:没错,在Boost或C++线程库中没有信号量,正如我的答案所说的。从概念上讲,信号量或管道可能被认为稍微干净一些,因为它是单个对象,不涉及任何外部共享状态。就我个人而言,我更喜欢通过消息队列等进行更高级别的同步,避免显式共享状态,但遗憾的是,这并没有纳入本版本的标准。显然,如果后续处理将执行额外的操作,包括在同一互斥体上进一步同步,则必须使用解锁。事实上,我并不太喜欢作用域锁定,因为这个原因以及它所鼓励的丑陋的内联块编码;我更喜欢Java语法。@MikeC:Scoped锁定是必要的,如果你做了任何可能引发异常的事情,除非你使用更难看的try/catch/rethrow块,这就是我不喜欢Java语法的原因。@MikeSeymour:我们必须同意,对于非关键字绑定的开-闭大括号结构与那些带有诸如try-and-catch等关键字的结构的相对难看性,我们有不同的看法。为了引入作用域而进行的缩进很简单。:)作为替代方案,我也喜欢Python的
@MikeC。很明显,您将把这个同步协议放在它自己的函数中,在做其他事情之前调用它。好的功能分解需要它,独立于释放锁的问题。至于Java语法。。。在Java中,锁定是语言的一部分,它的实现方式意味着一个函数不能返回锁定的对象。这是一个非常重要和有用的习惯用法。@MikeC在genral中使用try/finally而不是析构函数。。。破坏者将责任交给需要它的物品的作者;try/catch将其置于客户手中。Java代码中最常见的错误之一是客户机忘记了对需要“销毁”的对象(例如需要关闭的流)执行try/finally。