如何降低生产者获得锁的可能性,而消费者在使用std::condition_variable时无法获得锁?
How to decrese the possibility of the producer acquiring the lock whereas the consumer could not get the lock when using std::condition_variable?
如何降低生产者(即下面代码片段代码中的主线程(获取锁而消费者(即等待线程(无法获得锁的可能性?如果你能告诉我一种避免它的方法,那就更好了。我认为使用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,引用自 en.cppreference.com/w/cpp/thread/condition_variable/notify_one(:
#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 == 1n";
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();
}
如果你把它作为一个原子变量,你可以完全等待done
没有锁。在这种情况下,这对我来说甚至比使用互斥锁更有意义。但是,这并没有改变忙于等待的整个概念,即循环旋转直到设置done
。
或者,您可以等待设置done
而不阻塞 CPU 内核。只需使用相同的条件变量概念。您甚至可以使用用于同步i
的相同条件变量。此方法的演示如下:https://en.cppreference.com/w/cpp/thread/condition_variable。
问题是这两种解决方案中哪一种"更好"。我可能更喜欢第一个基于旋转的解决方案,因为可以预期,等待时间会非常短(如果系统没有超额订阅等(。
为什么你认为使用睡眠是一个不好的想法? 使用std::this_thread::sleep_for(std::chrono::milliseconds(100((是非常标准的;在 while(true( 线程中,它也会解决您的问题。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从持续时间构造std::chrono::system_clock::time_point
- std::具有相同基类的类的变体
- std::向量与传递值的动态数组
- 使用std::vector的OpenCL矩阵乘法
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- std::condition_variable::wait()如何评估给定的谓词
- 如何获取std::result_of函数的返回类型
- std::原子加载和存储都需要吗
- 将对象移动到std::shared_ptr
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 使用一个考虑到std::map中键值的滚动或换行的键
- 如何从 std::atomic 中提取指针 T<T>?
- 为什么 std::unique 不调用 std::sort?
- 使用std::函数映射对象方法
- 我需要std::condition,但有两个以上的选择