Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.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

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++11互斥行为_C++_Multithreading_C++11_Mutex - Fatal编程技术网

奇怪的C++11互斥行为

奇怪的C++11互斥行为,c++,multithreading,c++11,mutex,C++,Multithreading,C++11,Mutex,我正在尝试使用二进制信号量实现计数信号量 代码逻辑是众所周知的,在使用Qt的QMutex类之前已经对其进行了测试,并且已知它可以使用生产者-消费者多线程驱动程序进行正确测试。 我已经尝试过手动控制l互斥锁来锁定类、锁定保护和唯一锁定对象,但没有效果 尽管如此,调用acquire的线程似乎在块互斥上被阻塞,即使其他线程调用block.unlock也是如此。使代码工作的唯一方法是将block.lock行替换为whileblock.try\u lock;然后一切正常 如果我用一个条件变量替换块互斥体,

我正在尝试使用二进制信号量实现计数信号量

代码逻辑是众所周知的,在使用Qt的QMutex类之前已经对其进行了测试,并且已知它可以使用生产者-消费者多线程驱动程序进行正确测试。 我已经尝试过手动控制l互斥锁来锁定类、锁定保护和唯一锁定对象,但没有效果

尽管如此,调用acquire的线程似乎在块互斥上被阻塞,即使其他线程调用block.unlock也是如此。使代码工作的唯一方法是将block.lock行替换为whileblock.try\u lock;然后一切正常

如果我用一个条件变量替换块互斥体,代码就会工作

#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;
}
未定义的行为:

已经拥有互斥锁的线程无法调用try_lock,否则,行为未定义。线路阻塞时。尝试锁定;这是不正确的。 unlock只能由拥有互斥锁的线程调用,否则,行为未定义。 2也错了。如果代码起作用,那是一次意外


您需要一个适当的信号量实现,这是部分涉及的。

永远不要手动调用lock或unlock。相反,如果出于某种原因提前离开作用域,那么使用互斥锁可能会导致死锁。注意:互斥锁不是二进制信号量。如果您有一个二进制信号量或计数信号量,那么您可以像互斥一样使用它,但反过来则不正确。二进制信号量可以以互斥不能的方式使用。下面StaceyGirl的回答描述了一些你可以用二进制信号量做的事情,而用互斥器做不到。谢谢大家。非常感谢。