繁体   English   中英

std :: unique_lock的关系 <mutex> 和conditional_variable条件

[英]Relationship of std::unique_lock<mutex> and conditional_variable cond

这是我的代码:

class carl{
public:
int x = 0;
std::mutex _mu;
std::condition_variable cond;
bool donecreating = false;

void createFood(){


    if(x == 0){
    std::unique_lock<mutex> locker(_mu);
    x++;
    std::cout<<"creating food.."<<std::endl;
    cout<<"Food count: "<<x<<endl;
    locker.unlock();

    cond.notify_one();                                 //notify
    std::this_thread::sleep_for(chrono::seconds(1));   //sleep
    }

}   

void eatFood(){

    std::unique_lock<mutex> locker(_mu);                //lock
    std::cout<<"i am executing"<<std::endl;             //notif
    cond.wait(locker);                                  //wait


    x--;                                                //process food
    std::cout<<"eating food.."<<std::endl;  
    cout<<"Food left: "<<x<<endl;
    locker.unlock();

}   
};

功能又称线程一

void create(carl& carl){
for(int i=0;i>-100;i--){        //create 100 times

  carl.createFood();

}   

carl.donecreating  = true;      //done creating 100 food 
}

主要

int main(int argc, char** argv) {
carl c;                                    //init object
std::thread t1(create,std::ref(c));        //init thread


while(c.donecreating != true){            //exit condition is if the class is done creating food 100 times

c.eatFood();                            

}

t1.join();

return 0;
}

输出:

i am executing
creating food...
Food count: 1
eating food..
Food left: 0

我正在尝试跟踪我的代码,到目前为止,这是我的理解,需要澄清一下

1.)编译后,主线程(消费者)比生产者线程快,因此它首先被启动,并由cond.wait(locker);进入睡眠状态cond.wait(locker); 防止因为没有食物而无法进食。 但在cond.wait(locker);之前cond.wait(locker); std::unique_lock<mutex> locker(_mu); ,它是否自动解锁,以便其他线程在等待时可以访问它?

2.)如果首先触发了createFood (因为线程是基于处理器的?可能吗?),它将发送cond.notify_one(); 如果有一个,如果没有,那就继续做饭然后sleep 另一个线程将开始处理,因为mutex将被解锁,然后到达cond.wait(locker); 但是已经有了食物,所以不再需要sleep我发现的解决方案是通过实施spurious wake ,这是为了什么?

3.)我仍然对std::unique_lock<mutex> locker(_mu);很好奇std::unique_lock<mutex> locker(_mu); 例如,如果另一个线程到达该行代码并且当前处于锁定状态,该怎么办? 它会忽略下面的每一行,而是继续前进直到该代码块超出范围吗? 还是停在那条线上,等到解锁?

首先,由于createFood() if(x == 0) createFood()访问x未受保护,因此您的代码具有数据争用(因此存在未定义的行为)。 互斥量必须保护对x每次访问(包括读取和写入)。

它是否自动解锁,以便其他线程在等待时可以访问它?

是的, wait()在阻塞条件变量之前先解锁互斥锁,然后在互斥锁返回之前再次锁定互斥锁。

另一个线程将开始处理,因为互斥锁将被解锁,然后到达cond.wait(locker); 但是已经有了食物,所以不再需要睡眠。我发现的解决方案是通过实施虚假唤醒,这是为了什么?

不,寄生唤醒不是您可以控制的东西。 您的代码有两个问题:

  • 如您所见,它可能会错过通知。
  • eatFood()的等待可能会虚假结束,在这种情况下,实际上没有任何食物可吃,但是您也不处理这种情况。

解决方案是循环wait ,直到有食物可用。 这等效于运行带有谓词的wait版本:

while(x == 0) cond.wait(locker); 

要么

cond.wait(locker, [this](){ return x > 0; });

我仍然对std::unique_lock<mutex> locker(_mu);很好奇std::unique_lock<mutex> locker(_mu); 例如,如果另一个线程到达该行代码并且当前处于锁定状态,该怎么办? 它会忽略下面的每一行,而是继续前进直到该代码块超出范围吗? 还是停在那条线上,等到解锁?

后者。 在该行之后,互斥锁被线程构造locker 这意味着需要阻塞并等待。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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