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

标签 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*/){
    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.wait, 互斥锁永远无法解锁。

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

最佳答案

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

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

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

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

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

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

相关文章:

c - 就 CPU 时间而言,等待互斥量与等待信号量

java - Android SQL 数据库打开和关闭 - 竞争条件

c++ - Boost Beast 握手 : sslv3 alert handshake failure error

java - 在 Java 中是否有更简单的方法来知道被拒绝的任务(由执行器)是否已作为 "CallerRunsPolicy"运行?

c++ - 我无法打开可变文件名

c++ - 防止为给定类型实例化模板化成员函数

c++ - 如何在另一个类中创建一个类的参数化构造函数作为数据成员?

c++ - 这是我想使用 "using"的情况吗?

c++ - 在 Visual Studio 中直接调用 MATLAB(多线程)

c++ - 使用较新的 IDE 重新编译源代码的好处