gpt4 book ai didi

c++ - C++11中如何正确解决生产者消费者

转载 作者:行者123 更新时间:2023-11-30 03:30:59 26 4
gpt4 key购买 nike

我正在尝试解决 C++11 中的生产者消费者问题。我有一个保存资源的对象,多个线程可以添加或消耗这些资源。我的问题是当我尝试实现时该对象的“可用时使用”方法。请假设插入/删除操作的复杂性微乎其微。

对代码逻辑的一些解释。

struct ResourceManager{
std::mutex mux;
std::unique_lock lock{mux};
std::condition_variable bell;

void addResource(/*some Resource*/){
lock.lock();
//add resource
lock.unlock();
bell.notify_one(); //notifies waiting consumer threads to consume
}

T getResource(){
while(true){
lock.lock();
if(/*resource is available*/){
//remove resource from the object
lock.unlock();
return resource;
}else{
//new unique lock mutex object wmux creation
lock.unlock(); //problem line
bell.wait(wmux); //waits until addResource rings the bell
continue;
}
}
}

};

假设以下场景:
- 两个线程,T1,T2,几乎同时调用addResource,getResource。

-T2锁住mutex,发现没有可用的资源,
所以它必须阻塞直到有新资源可用。
因此它解锁互斥锁并设置等待铃。

-T1 跑得更快。当互斥量解锁时,
它立即添加资源,并在T2设置等待铃之前,
T1 已经按铃,没有通知任何人。

-T2 无限期地等待铃声响起,但不会添加更多资源。

我假设锁定互斥锁的线程可能是唯一的解锁它。因此,如果我尝试在解锁互斥量之前调用 bell.wait,互斥锁永远无法解锁。

如果可能的话,我想使用无时间等待或多次检查的解决方案。
那么在 C++11 中我可以用什么方法解决这个问题呢?

最佳答案

    lock.unlock(); //problem line
bell.wait(wmux); //waits until addResource rings the bell

是的,这确实是问题所在。

要按设计正确使用条件变量,您不要在对其相关条件变量wait()之前解锁互斥量。 wait() 在等待期间对条件变量自动解锁,并在线程被notify() 后重新获取互斥量。解锁并等待和通知后唤醒并锁定都是原子操作。

Allnotify() 应该在互斥量被锁定时发出。所有 wait() 也在互斥量完全锁定时完成。正如我提到的,鉴于 notify() 是原子的,这导致所有与互斥锁相关的操作都是原子的并且完全排序,包括管理受互斥锁保护的资源,以及通过条件变量进行线程通知,现在也受到互斥体的保护。

可以实现一些设计模式,在不使用互斥保护的情况下通知条件变量。但是它们更难正确实现并仍然实现线程安全语义。除了互斥量保护的所有其他内容之外,让所有条件变量操作也受互斥量保护,实现起来要简单得多。

关于c++ - C++11中如何正确解决生产者消费者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44577856/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com