我正在尝试解决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;
}
}
}
};假设以下场景:
-Two线程、T1、T2几乎同时调用addResource和getResource。
-T2锁定互斥,并发现没有更多的资源可用,
所以它必须阻塞,直到有新的资源可用。
所以它解锁互斥锁并设置铃声等待。
-T1运行匹配速度更快。当互斥锁被解锁时,
它立即添加资源,并且在T2设置等待铃之前,
T1已经按了门铃,它不会通知任何人。
-T2无限期地等待铃声响起,但是没有添加更多的资源。
我假设锁定互斥的线程可能是唯一解锁它的线程。因此,如果我尝试在解锁互斥锁之前调用bell.wait,互斥锁永远不会被解锁。
如果可能的话,我想使用没有时间等待或多次检查的解决方案。
那么在C++11中我可以用什么方法来解决这个问题呢?
发布于 2017-06-16 06:24:02
lock.unlock(); //problem line
bell.wait(wmux); //waits until addResource rings the bell是的,这确实是问题所在。
要按照设计正确使用条件变量,在对相关的条件变量执行wait()操作之前,不要对互斥锁执行wait()操作。对条件变量执行wait()操作会在等待期间自动解锁该条件变量,并在线程被notify()-ed后重新获取互斥锁。解锁并等待和通知并锁定后唤醒都是原子操作。
应在互斥锁被锁定时发出所有notify()%s。当互斥锁被完全锁定时,所有的wait()也会被完成。正如我所提到的,由于notify()是原子的,因此所有与互斥锁相关的操作都是原子的,并且是完全顺序的,包括管理互斥锁保护的资源,以及通过条件变量进行线程通知,条件变量现在也受互斥锁保护。
有一些设计模式可以在不使用互斥保护的情况下通知条件变量。但是它们很难正确实现,并且仍然实现线程安全的语义。除了互斥锁保护的所有其他操作外,所有条件变量操作也由互斥锁保护,实现起来要简单得多。
发布于 2017-06-16 09:03:30
需要在互斥锁上向std::condition_variable::wait传递一个锁定的std::unique_lock。wait将解锁互斥锁作为其操作的一部分,并将在它返回之前重新锁定它。
使用像std::lock_guard和std::unique_lock这样的锁保护的正常方法是在本地构造它们,并让它们的构造函数锁定你的互斥锁,让它们的析构函数解锁它。
此外,您还可以通过向std::condition_variable::wait提供谓词来避免原始代码中的外部while循环。
struct ResourceManager {
std::mutex mux;
std::condition_variable bell;
void addResource(T resource)
{
std::lock_guard<std::mutex> lock{mux};
// Add the resource
bell.notify_one();
}
T getResource()
{
std::unique_lock<std::mutex> lock{mux};
bell.wait(lock, [this](){ return resourceIsAvailable(); });
return // the ressource
}
};https://stackoverflow.com/questions/44577856
复制相似问题