简体   繁体   English

奇怪的C ++ 11互斥行为

[英]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_guardunique_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM