0

这个问题是对这个问题的跟进。总结是——我有一个服务器调用 close() 来完成连接,但似乎关闭序列从未发生过。客户端继续等待更多数据。close() 在服务器中返回 0。即使正确实现了条件队列,将我的线程安全队列从条件等待切换到信号量也解决了这个问题。我正在发布我的代码,看看是否有人对我有任何启发。

基于条件的队列:

  TASK *head;
  pthread_mutex_t mutex;
  pthread_cond_t cond;

  void init( ) {
    head = NULL;
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);
  }

  TASK *get( ) {
    pthread_mutex_lock( &mutex );
    while(!head)
      pthread_cond_wait(&cond, &mutex);
    TASK *res = head;
    head = head->next;
    pthread_mutex_unlock( &mutex );
    return res;
  }

  void add( TASK *t ) {
    pthread_mutex_lock( &mutex );
    t->next = head;
    head = t;
    pthread_cond_broadcast( &cond );
    pthread_mutex_unlock( &mutex );
  }

我确实意识到这是一个 LIFO 队列,下一个是 FIFO,但我只包含了有趣的位,因此它既快速又易于阅读。

基于信号量的队列:

  TASK *buf;
  TASK *next_reader;
  TASK *next_writer;
  TASK *endp;
  pthread_mutex_t writer_mutex;
  pthread_mutex_t reader_mutex;
  sem_t writer_sem;
  sem_t reader_sem;

  void init( int num_tasks ) {
    buf = calloc(sizeof(TASK), num_tasks);
    next_reader = buf;
    next_writer = buf;
    endp = buf + num_tasks;
    sem_init(&writer_sem, 0, num_tasks);
    sem_init(&reader_sem, 0, 0);
    pthread_mutex_init(&writer_mutex, NULL);
    pthread_mutex_init(&reader_mutex, NULL);
  }

  TASK *get( ) {
    TASK *res = NULL;
    sem_wait(&reader_sem);
    pthread_mutex_lock(&reader_mutex);
    res = next_reader;
    next_reader++;
    if(next_reader == endp)
      next_reader = buf;
    pthread_mutex_unlock(&reader_mutex);
    sem_post(&writer_sem);
    return res;
  }

  void add( TASK *t ) {
    sem_wait(&writer_sem);
    pthread_mutex_lock(&writer_mutex);
    *next_writer = *item;
    next_writer++;
    if(next_writer == endp)
      next_writer = buf;
    pthread_mutex_unlock(&writer_mutex);
    sem_post(&reader_sem);
  }

我一生都看不到从条件队列到信号量队列的更改将如何解决我发布的上一个问题,除非如果线程正在关闭套接字并且在关闭期间调用 pthread_cond_broadcast 会发生一些时髦的事情。我假设一个操作系统错误,因为我找不到任何谴责我正在做的事情的文档。没有从信号处理程序调用队列操作。这是我的发行版:

Linux版本:2.6.21.7-2.fc8xen

Centos 版本:5.4(最终版)

谢谢

编辑----我刚刚添加了我正在做的初始化。在实际代码中,这些都是在模板类中实现的。我刚刚包括了相关部分。

4

0 回答 0