C++ 使用C+中的std::condition_变量将线程置于死锁状态是否有风险+;?

C++ 使用C+中的std::condition_变量将线程置于死锁状态是否有风险+;?,c++,multithreading,C++,Multithreading,这是一个更具理论性的问题。我已经看到了两个带有std::condition\u变量的示例,它似乎让线程休眠,直到满足一个条件为止。这是某种种族的旗帜,很有意义 但是,如果变量总是被更改,那么线程可能会被唤醒以检查条件,然后再次进入睡眠状态,因为当谓词为true时,线程无法保持状态,因此我可能会将线程置于“昏迷”状态 那么,在我总是更改它的情况下使用它时,std::condition\u variable是否不安全?您似乎在谈论某种“活锁”。死锁是指一个或多个线程在等待释放锁时没有进展的情况。 L

这是一个更具理论性的问题。我已经看到了两个带有
std::condition\u变量的示例,它似乎让线程休眠,直到满足一个条件为止。这是某种种族的旗帜,很有意义

但是,如果变量总是被更改,那么线程可能会被唤醒以检查条件,然后再次进入睡眠状态,因为当谓词为true时,线程无法保持状态,因此我可能会将线程置于“昏迷”状态


那么,在我总是更改它的情况下使用它时,
std::condition\u variable
是否不安全?

您似乎在谈论某种“活锁”。死锁是指一个或多个线程在等待释放锁时没有进展的情况。 Livelock与之类似,但过程的状态不断变化,但仍然没有进展。我们还可以讨论“实际上是livelocked”,即线程没有足够的机会取得足够的进展

对于观察者来说,livelock和实际的livelock通常看起来非常像真正的死锁

您应该设计您的程序逻辑以避免livelock。它可以是不平凡的。例如,许多形式的锁是不公平的。也就是说,当多个线程正在等待一个释放的锁时,首先请求它的锁不保证下一个会收到它

事实上,许多操作系统锁本质上是不公平的,例如,将锁提供给更容易唤醒(例如加载到内核并挂起)而不是更难唤醒(从内核卸载并需要重新加载才能恢复执行)的线程

这个问题没有给出太多细节,所以很难判断情况。 如果某个特定线程(或某类线程)需要优先级,您可以引入一个标志,告诉低优先级线程在优先级线程正在等待(并且可以运行)时不要获取锁,例如
(c&&!(p&&priority\u waiting))
其中
c
是低优先级线程的逻辑条件,
p
是优先级线程的逻辑条件

当然,您应该避免线程等待潜在瞬态条件的逻辑。 假设您有一个监视器线程,它产生1000个周期的输出。像
(cycles%1000==0)
这样的等待条件很容易错过计数器的点击。它们更可能类似于
(cycles lcycles>=0)
,其中
lcycles
是上次监视器恢复处理时的循环计数。这确保了监视器通常会得到一个锁,它可能(出于实际目的)几乎永远不会被捕获

在该示例中,线程正在等待(a)获得锁的机会和(b)某个瞬态条件。存在这样一种风险,即两种情况很少同时发生,线程可能被实时锁定或实际上被实时锁定,并且进展不足

简而言之,确保线程在条件通过时恢复,而不是在条件完全通过时恢复


您可以引入一个严格的队列来轮换线程。除非文档中明确承诺公平,否则不要认为这就是你所拥有的。

你似乎在谈论某种“活锁”。死锁是指一个或多个线程在等待释放锁时没有进展的情况。 Livelock与之类似,但过程的状态不断变化,但仍然没有进展。我们还可以讨论“实际上是livelocked”,即线程没有足够的机会取得足够的进展

对于观察者来说,livelock和实际的livelock通常看起来非常像真正的死锁

您应该设计您的程序逻辑以避免livelock。它可以是不平凡的。例如,许多形式的锁是不公平的。也就是说,当多个线程正在等待一个释放的锁时,首先请求它的锁不保证下一个会收到它

事实上,许多操作系统锁本质上是不公平的,例如,将锁提供给更容易唤醒(例如加载到内核并挂起)而不是更难唤醒(从内核卸载并需要重新加载才能恢复执行)的线程

这个问题没有给出太多细节,所以很难判断情况。 如果某个特定线程(或某类线程)需要优先级,您可以引入一个标志,告诉低优先级线程在优先级线程正在等待(并且可以运行)时不要获取锁,例如
(c&&!(p&&priority\u waiting))
其中
c
是低优先级线程的逻辑条件,
p
是优先级线程的逻辑条件

当然,您应该避免线程等待潜在瞬态条件的逻辑。 假设您有一个监视器线程,它产生1000个周期的输出。像
(cycles%1000==0)
这样的等待条件很容易错过计数器的点击。它们更可能类似于
(cycles lcycles>=0)
,其中
lcycles
是上次监视器恢复处理时的循环计数。这确保了监视器通常会得到一个锁,它可能(出于实际目的)几乎永远不会被捕获

在该示例中,线程正在等待(a)获得锁的机会和(b)某个瞬态条件。存在这样一种风险,即两种情况很少同时发生,线程可能被实时锁定或实际上被实时锁定,并且进展不足

简而言之,确保线程在条件通过时恢复,而不是在条件完全通过时恢复


您可以引入一个严格的队列来轮换线程。除非文档中明确承诺了公平性,否则不要假设这就是你所拥有的。

这就是为什么
条件变量总是与l组合使用的原因
Lock mutex
Check condition (it's false)
Unlock mutex and start waiting (these happen at the exact same time)
Finish waiting and lock mutex
Check condition (it's true)
Unlock mutex
Lock mutex
Change condition
Unlock mutex
Notify condition variable