Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何正确解决C++;11_C++_Multithreading_C++11_Mutex - Fatal编程技术网

C++ 如何正确解决C++;11

C++ 如何正确解决C++;11,c++,multithreading,c++11,mutex,C++,Multithreading,C++11,Mutex,我试图在C++11中解决生产者-消费者问题。 我有一个保存资源的对象,多个线程可以 添加或消耗这些资源。我的问题是当我试图实现 该对象上的“可用时使用”方法。 请假定插入/删除操作的复杂性很小 代码中逻辑的一点解释 struct ResourceManager{ std::mutex mux; std::unique_lock lock{mux}; std::condition_variable bell; void addResource(/*some Resource*/)

我试图在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锁定互斥锁,并发现没有更多可用资源,
因此它必须阻止,直到有新的资源可用。
因此,它解锁互斥锁并设置等待的铃声

-T1跑比赛速度更快。当互斥锁解锁时,
它立即添加资源,在T2设置等待铃之前,
T1已经按铃了,没有人知道

-T2无限期地等待铃声响起,但没有添加更多的资源

我假设锁定互斥对象的线程可能是唯一的线程 打开它。如果我试着打电话给bell,在解锁互斥锁之前等待, 互斥锁永远无法解锁

如果可能,我希望使用无时间等待或多次检查解决方案。
在C++11中,我可以用哪种方法解决这个问题

    lock.unlock(); //problem line
    bell.wait(wmux); //waits until addResource rings the bell
是的,这确实是问题所在

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

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


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

std::condition\u variable::wait
需要在互斥体上传递一个锁定的
std::unique\u lock
wait
将解锁互斥锁作为其操作的一部分,并在返回前重新锁定互斥锁

使用锁防护(如
std::lock\u-guard
std::unique\u-lock
等)的正常方法是在本地构造它们,并让它们的构造函数锁定互斥锁,而它们的析构函数则解锁互斥锁

另外,通过为
std::condition\u 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
  }
};
struct ResourceManager{
std::互斥多路复用器;
std::条件变量钟;
void addResource(T资源)
{
std::lock_guard lock{mux};
//添加资源
通知某人;
}
T getResource()
{
std::unique_lock lock{mux};
wait(lock,[this](){return resourceisavaailable();});
返回//ressource
}
};

可能与您的问题无关,但请使用锁防护装置,如
std::unique_lock
锁定/解锁互斥锁。lock是唯一的锁什么是
wmux
?您应该将
lock
锁定,然后执行
bell。等待(锁定)
,以避免出现竞争条件。@fructedsoul噢,对不起。但这不是如何使用它。通常情况下,您没有成员变量,但有一个局部变量,在离开互斥对象的作用域时只会解锁互斥对象。@fructedsoul:我已经删除了我的解决方案,请您在示例中检查unique_lock和condition_变量的正确用法,这正是您想要做的。谢谢您的回答。因此,如果我理解正确,在addResource中,应该在解锁互斥锁之前调用bell.notify_one()。另外,在getResource中,我应该删除lock.unlock(),并使用bell.wait(lock)代替bell.wait(wmux);我说得对吗?听起来对;当然,这取决于实际的实现细节,因为您只在问题中总结了代码。注意:“lock-std::unique_lock类型的对象,必须由当前线程锁定”。感谢您的时间,您的回答很好地描述了其他人之前已经回答的问题。很遗憾,他删除了他的帖子:S