在我的程序中,我有一个互斥锁和两个线程。其中一个线程经常获得锁定。另一个线程试图获取,但必须永远等待。
可能是因为锁定在释放之后如此快速地获得了另一个线程没有机会?互斥体总是给每个人一个机会吗?如果没有,什么是一个好的解决方案?(某种FIFO锁?)
我正在使用std :: mutex和std :: lock_guard
问题扩展 seccpur指出std :: condition_variable可以解决这个问题。这如何与三个线程一起扩展? std :: condition_variable是否确保每个线程都转向?假设你使用notify_one()。
答案 0 :(得分:2)
std :: mutex不保证给每个人一个平等的机会。因此,一个线程可能会使另一个线程挨饿。您可以尝试的第一件事是插入std::this_thread::yield()并查看它是否有帮助。如果这没有帮助,那么您的代码必须具有逻辑错误。发布部分代码,我们可以帮助您进一步诊断。
答案 1 :(得分:1)
使用seccpur的提示我想出了以下解决方案,以防止挨饿单个线程。
#include <condition_variable>
#include <mutex>
#include <atomic>
class NoStarveLock
{
std::condition_variable condition;
std::atomic_flag flag = ATOMIC_FLAG_INIT;
std::mutex conditionLock;
public:
void lock()
{
std::unique_lock<std::mutex> lck(conditionLock);
while (flag.test_and_set()) // multiple threads can wake up at the same time, so use a set+test
{
condition.wait(lck); // wait for a wakeup
}
}
void unlock()
{
std::unique_lock<std::mutex> lck(conditionLock);
flag.clear();
condition.notify_all();
}
};
答案 2 :(得分:0)
使用std::mutex
,std::lock_guard
,std::unique_lock
(读者)和std::condition_variable
的示例。
_mutexLockCondition,_mutexObject和_dataContainer在ReaderClass和WriterClass之间共享。
我觉得实际的数据容器有点模糊,所以getDataContainer()
和addDataToContainer()
取决于您。
std::shared_ptr< Data > ReaderClass::read()
{
std::unique_lock< std::mutex > lock( _mutexObject );
// handle spurious wakeup from waitForMessageNotification
while( _dataContainer.empty() )
{
if( waitForMessageNotification( lock ) )
{
// timeout occurred, return nullptr to prevent blocking
return nullptr;
}
}
return getDataFromContainer();
}
bool ReaderClass::waitForNotification( unique_lock< mutex > & lock )
{
//_mutexLockCondition is a std::condition_variable
return _mutexLockCondition.wait_for( lock, std::chrono::milliseconds( 100 ) )
== std::cv_status::timeout;
}
void WriterClass::write( std::shared_ptr< Data > dataPtr )
{
std::lock_guard< mutex > lock( _mutexObject );
addDataToContainer( dataPtr );
_mutexLockCondition.notify_one();
}