如何降低使用std :: condition_variable时生产者获得锁而消费者无法获得锁的可能性?

问题描述 投票:0回答:2

如何降低生产者(即下面代码片段代码中的主线程)获得锁而消费者(即等待线程)无法获得锁的可能性?如果您能告诉我一种避免它的方法,那就更好了。我认为使用std::thread::sleep_forstd::thread::yield不是一个好主意。并且我进行了一些测试,发现使用std::thread::yield时没有任何效果。

我考虑了很长时间,很高兴能对此问题提供帮助。

如果运行代码段,您可能会看到这样的输出:

Waiting... 
test 
Notifying falsely... 
Notifying true change... 
Notifying true change... 
Notifying true change... 
Notifying true change... 
Notifying true change... 
Notifying true change...
(**many many such output**)
Notifying true change... 
test 
...finished waiting. i == 1

这里是相关代码段(检查https://godbolt.org/z/9dwDJN):

#include <iostream>
#include <condition_variable>
#include <thread>
#include <chrono>

std::condition_variable cv;
std::mutex cv_m;
int i = 0;
bool done = false;

void waits()
{
    std::unique_lock<std::mutex> lk(cv_m);
    std::cout << "Waiting... \n";
    cv.wait(lk, []{std::cout<<"test"<<std::endl; return i == 1;});
    std::cout << "...finished waiting. i == 1\n";
    done = true;
}

void signals()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Notifying falsely...\n";
    cv.notify_one(); // waiting thread is notified with i == 0. 
    // cv.wait wakes up, checks i, and goes back to waiting 

    std::unique_lock<std::mutex> lk(cv_m);
    i = 1;
    while (!done)
    {
        std::cout << "Notifying true change...\n";
        lk.unlock();
        cv.notify_one(); // waiting thread is notified with i == 1, cv.wait returns 
        //std::this_thread::sleep_for(std::chrono::seconds(1));   // I don't think it is good method.
        //std::this_thread::yield();  //Maybe, this does not work.
        lk.lock();
    }
}

int main()
{
    std::thread t1(waits), t2(signals);
    t1.join();
    t2.join();
}
c++ c++11 conditional-statements mutex race-condition
2个回答
0
投票

您为什么认为使用睡眠是一个坏想法?使用std :: this_thread :: sleep_for(std :: chrono :: milliseconds(100))的标准在while(true)线程中,它也可以解决您的问题。


-1
投票

您对条件变量的使用不正确。信令线程中的使用模式为:

Lock
Modify
Notify
Unlock

等待线程中的使用模式:

Lock
while condition is False:
    Wait
// Hurrah! the conditon if True
Make use of the condition
Unlock

等待线程在不锁定互斥体的情况下谦卑地等待条件,只是在偶发的唤醒情况下检查此条件。信令线程可以选择更新条件的时间,并且此时锁定互斥锁没有问题。因此,您不需要任何sleepyield

© www.soinside.com 2019 - 2024. All rights reserved.