C++20 信号量的生产者和消费者问题

producer and consumer problem with c++20 semaphore

提问人:Dengzhi Zhang 提问时间:11/8/2023 最后编辑:Nicol BolasDengzhi Zhang 更新时间:11/8/2023 访问量:59

问:

这是使用改编自维基百科 https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem 的 c++20 信号量的生产者和消费者问题实现。我们还需要 std::lock_guardstd::mutex g(mtx);吗?

#include <thread>
#include <mutex>
#include <semaphore>

std::queue<int> q;
std::counting_semaphore<N> full{0};
std::counting_semaphore<N> empty{N};
std::mutex mtx;

void produce() {
  for (;;) {
    int item = 0;
    empty.acquire();
    {
      std::lock_guard<std::mutex> g(mtx);
      q.push(item);
    }
    full.release();
  }
}

void consume() {
  for (;;) {
    full.acquire();
    {
      std::lock_guard<std::mutex> g(mtx);
      int item = q.front();
      q.pop();
    }
    empty.release();
  }
}

int main() {
  std::thread t1(producer);
  std::thread t2(consumer);
  t1.join();
  t2.join();
}

据我了解,信号量已经排除了。为什么我们需要另一个lock_guard?

C++ C++20 互斥信号 生产者-消费者

评论

1赞 Pepijn Kramer 11/8/2023
因为你可以继续生产东西和消费东西并行,而你既不是空的也不是满的。因此,q.push/q.pop 仍然可以同时发生。想想 N==4 和你正在生产项目 #3 并消耗项目 #2 的情况
4赞 Cem Polat 11/8/2023
信号量为生产者和使用者线程提供互斥,但不能保护共享队列免受并发访问。互斥锁需要确保一次只能有一个线程修改队列,否则可能会出现数据损坏或不一致。信号量仅控制有多少线程可以进入临界区,但不能保证临界区内操作的原子性。因此,您仍然需要lock_guard来获取和释放互斥锁,当您从队列中推送或弹出时。
0赞 Louis Go 11/9/2023
跨线程共享的读/写访问权限的任何内容都应被锁定。

答: 暂无答案