如何降低生产者(即下面代码片段代码中的主线程)获得锁而消费者(即等待线程)无法获得锁的可能性?如果您能告诉我一种避免它的方法,那就更好了。我认为使用std::thread::sleep_for
或std::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();
}
您为什么认为使用睡眠是一个坏想法?使用std :: this_thread :: sleep_for(std :: chrono :: milliseconds(100))的标准在while(true)线程中,它也可以解决您的问题。
您对条件变量的使用不正确。信令线程中的使用模式为:
Lock
Modify
Notify
Unlock
等待线程中的使用模式:
Lock
while condition is False:
Wait
// Hurrah! the conditon if True
Make use of the condition
Unlock
等待线程在不锁定互斥体的情况下谦卑地等待条件,只是在偶发的唤醒情况下检查此条件。信令线程可以选择更新条件的时间,并且此时锁定互斥锁没有问题。因此,您不需要任何sleep
,yield
等