【发布时间】:2026-01-03 08:10:01
【问题描述】:
我正在尝试使用二进制信号量来实现计数信号量。
代码逻辑是众所周知的,并且在使用 Qt 的QMutex 类之前已经过测试,并且可以正常工作(使用生产者-消费者多线程驱动程序进行测试)。
我已经尝试手动控制l mutex(锁定类)、lock_guard 和unique_lock 对象,但没有效果。
调用acquire() 的线程似乎在block 互斥锁上被阻塞(尽管并非始终如此),即使其他线程调用block.unlock() 也是如此。使代码工作的唯一方法是将block.lock() 行替换为while(block.try_lock()); 然后一切正常。
如果我将 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;
}
【问题讨论】:
-
永远不要手动拨打
lock或unlock。而是使用std::lock_guardand friends,否则如果您出于某种原因提前离开范围,您将面临死锁的风险。 -
注意:mutex 不是二进制信号量。如果你有一个二进制信号量(或计数信号量),那么你可以像互斥体一样使用它,但反之则不然。可以以互斥锁不能使用的方式使用二进制信号量。 StaceyGirl 的回答(如下)描述了一些你可以用二进制信号量做的事情,而你不能用互斥锁做。
-
谢谢大家。非常感谢。
标签: c++ multithreading c++11 mutex