[英]Strange C++11 mutex behavior
I am trying to implement a counting semaphore using binary ones. 我正在尝试使用二进制的实现计数信号量。
The code logic is well known and it has been tested before using Qt's QMutex
class and it is known to work properly (tested with a producer-consumer multithreaded driver). 代码逻辑是众所周知的,并且在使用Qt的
QMutex
类之前已经过测试,并且可以正常工作(已使用生产者-消费者多线程驱动程序进行了测试)。 I have tried manual control of the l
mutex (to lock the class), lock_guard
and unique_lock
objects, to no effect. 我尝试过手动控制
l
互斥锁(以锁定类), lock_guard
和unique_lock
对象,但没有任何效果。
A thread calling acquire()
seems to get blocked on the block
mutex (not consistently though), even when other threads call block.unlock()
. 甚至当其他线程调用
block.unlock()
时,调用acquire()
线程似乎也会在block
互斥体上被block
(尽管block.unlock()
。 The only way to make the code work is to replace the block.lock()
line with while(block.try_lock());
使代码起作用的唯一方法是用
while(block.try_lock());
替换block.lock()
行while(block.try_lock());
Then everything works properly. 然后,一切正常。
The code works if I replace the block
mutex with a condition variable. 如果我用条件变量替换
block
互斥锁,则该代码有效。
#include <mutex>
class semaphore
{
private:
int value=0;
std::mutex l, block;
public:
semaphore(int i=0);
semaphore(const semaphore&)=delete;
semaphore(const semaphore&&)=delete;
semaphore & operator=(const semaphore&)=delete;
semaphore & operator=(const semaphore&&)=delete;
void acquire();
void acquire(unsigned int i);
void release(unsigned int i=1);
int available();
bool try_acquire(unsigned int i=1);
};
//---------------------------------
semaphore::semaphore(int i)
{
value=i;
block.lock(); // make sure that any thread trying to lock will block
}
//---------------------------------
void semaphore::acquire()
{
l.lock();
value--;
if(value <0)
{
l.unlock(); // release the semaphore while waiting
while( block.try_lock()); // LINES IN QUESTION
//block.lock(); // LINES IN QUESTION
}
else
l.unlock();
}
//---------------------------------
void semaphore::acquire(unsigned int i)
{
while(i--)
this->acquire();
}
//---------------------------------
void semaphore::release(unsigned int i)
{
l.lock();
while(i--)
{
value++;
if(value <=0)
block.unlock();
}
l.unlock();
}
//---------------------------------
int semaphore::available()
{
std::unique_lock<std::mutex> guard(l);
return value;
}
//---------------------------------
bool semaphore::try_acquire(unsigned int i)
{
l.lock();
bool res=false;
if(value>=(int)i)
{
value-=i;
res=true;
}
l.unlock();
return res;
}
Undefined behaviors: 未定义的行为:
try_lock
cannot be called by a thread that already owns the mutex, otherwise, the behavior is undefined. try_lock
不能由已经拥有互斥锁的线程调用,否则,行为是不确定的。 Line while( block.try_lock());
while( block.try_lock());
is incorrect. unlock
can only be called by a thread that owns the mutex, otherwise, the behavior is undefined. unlock
,否则行为是不确定的。 The #2 is also wrong for QtMutex
. #2对于
QtMutex
也是错误的。 If the code was "working", it did so by an accident. 如果代码是“有效的”,那么它是偶然发生的。
You need a proper semaphore implementation, something that is partially covered here . 您需要一个适当的信号量实现, 此处部分介绍了该实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.