c++ - 这个生产者/消费者的实现有什么问题?

标签 c++ pthreads

所以我正在考虑在 C++ 中使用简单的生产者/消费者队列。我最终将使用 boost 进行线程处理,但此示例仅使用 pthreads。我最终也会使用更多面向对象的方法,但我认为这会掩盖我目前感兴趣的细节。

无论如何,我担心的具体问题是

  1. 由于此代码使用 std::deque 的 push_back 和 pop_front - 它可能在不同线程中分配和释放底层数据 - 我认为这是不好的(未定义的行为) - 避免这种情况的最简单方法是什么?
  2. 没有任何东西被标记为易变的。但是重要的位是受互斥锁保护的。我是否需要将任何东西标记为 volatile 的,如果需要怎么办? - 我不认为我这样做是因为我相信互斥锁包含适当的内存屏障等,但我不确定。

还有其他明显的问题吗?

无论如何这是代码:

#include <pthread.h>
#include <deque>
#include <iostream>

struct Data
{
  std::deque<int> * q;
  pthread_mutex_t * mutex;
};

void* producer( void* arg )
{
  std::deque<int> &q = *(static_cast<Data*>(arg)->q);
  pthread_mutex_t * m =  (static_cast<Data*>(arg)->mutex);

  for(unsigned int i=0; i<100; ++i)
  {
    pthread_mutex_lock( m );
    q.push_back( i );
    std::cout<<"Producing "<<i<<std::endl;
    pthread_mutex_unlock( m );
  }
  return NULL;
}

void* consumer( void * arg )
{
  std::deque<int> &q = *(static_cast<Data*>(arg)->q);
  pthread_mutex_t * m =  (static_cast<Data*>(arg)->mutex);

  for(unsigned int i=0; i<100; ++i)
  {
    pthread_mutex_lock( m );
    int v = q.front();
    q.pop_front();
    std::cout<<"Consuming "<<v<<std::endl;
    pthread_mutex_unlock( m );
  }  
  return NULL;
}

int main()
{
  Data d;

  std::deque<int> q;
  d.q = &q;

  pthread_mutex_t mutex;
  pthread_mutex_init( &mutex, NULL );
  d.mutex = & mutex;

  pthread_t producer_thread;
  pthread_t consumer_thread;

  pthread_create( &producer_thread, NULL, producer, &d );
  pthread_create( &consumer_thread, NULL, consumer, &d );

  pthread_join( producer_thread, NULL );
  pthread_join( consumer_thread, NULL );
}

编辑:

我最终放弃了这个实现,我现在使用来自 here 的代码的修改版本安东尼·威廉姆斯。我的修改版本可以找到here此修改版本使用更明智的基于条件变量的方法。

最佳答案

Since this code is using push_back and pop_front of std::deque - it's probably doing allocation and deallocation of the underlying data in different threads - I believe this is bad (undefined behaviour) - what's the easiest way to avoid this?

只要一次只有一个线程可以修改容器,就可以了。

Nothing is marked volatile. But the important bits are mutex protected. Do I need to mark anything as volatile and if so what? - I don't think I do as I believe the mutex contains appropriate memory barriers etc., but I'm unsure.

只要您使用互斥锁正确地控制对容器的访问,它就不需要是volatile(这取决于您的线程库,但它不会是一个很好的互斥锁如果它没有提供正确的内存屏障)。

关于c++ - 这个生产者/消费者的实现有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3278036/

相关文章:

c - pthread(段错误)

java - 来自 pthread_self() 的 Pthread id 与来自 d​​trace 脚本的数据不匹配

c++ - 如何将数字直接写入 ofstream 对象?

c++ - 发出信号并保持 pthread 打开的有效方法?

c - 报告计算进度的 C 方法是什么?

c++ - 单链表交换函数(int, int)

c - 使用 for 循环创建多个线程时的奇怪行为

c++ - winAPI C++ 禁用无线适配器

C++ HW 帮助使用堆栈

c++ - 派生类的重载 << 运算符表示无效操作数