POSIX Thread相关

1. 关于pthread_cond系列函数

pthread_cond_wait的参数里有一个mutex,其作用往往令人费解。

最近在考察OpenMAX系统发现这一部分的实现可能导致较大的风险。

一般而言有了这个mutex以后对于cond实现一些增强的特性就比较方便。

例如,如果要将cond用作semaphore,以下代码应该能起作用:

  1. sem_down(sem)
  2. {
  3.     pthread_mutex_lock(sem->mutex);
  4.     // critical section  
  5.     sem->count--;
  6.     if (sem->count < 0)
  7.     {
  8.         pthread_cond_wait(sem->cond, sem->mutex);    // the mutex is unlocked once the thread gets blocked
  9.         // mutex is locked and owned by the current thread again after it is scheduled to run when unblocked
  10.     }
  11.     pthread_mutex_unlock(sem->mutex)
  12. }
  13. sem_up(sem)
  14. {
  15.     pthread_mutex_lock(sem->mutex);    // absence of this mutex acquisition may cause severe error
  16.     sem->count++;
  17.     pthread_cond_signal(sem->cond);
  18.     pthread_mutex_unlock(sem->mutex)
  19. }

这样cond和count的操作被完全保护(原子化),同时由于pthread_cond_wait在cond阻塞情况下自动释放mutex又不至于导致死锁。

但是其前提条件是底层的OS正确地实现这几个POSIX接口的意图(这不是必然的)。否则需要通过时序的分析确定可能造成的问题。

注意在sem_up中如果不做互斥量保护则在如下情况下发生错误:

线程A阻塞在pthread_cond_wait,sem->count计数为-1;

线程B进入sem_down,并执行完成sem->count--后,调度到线程C;

线程C进入sem_up,执行sem->count++,和pthread_cond_signal,使得sem->count计数变为0,同时线程A被激活;

这样线程A可获得mutex并从sem_down返回;

线程B条件判断不成立不被阻塞,亦返回。但显然在这个序列中应该至少有一个线程被阻塞。(按理想顺序应该B被阻塞)

 

由于posix规定中关于pthread_cond_signal触发的说明是至少释放一个阻塞,于是存在同时释放多个阻塞的情形。如下代码也许可以解决这个问题:

  1. sem_down(sem)
  2. {
  3.     pthread_mutex_lock(sem->mutex);
  4.     // critical section   
  5.     sem->count--;
  6.     if (sem->count < 0)
  7.     {
  8. _again:
  9.         sem->nblocked++;    // count the number of blocked threads   
  10.         pthread_cond_wait(sem->cond, sem->mutex); 
  11.         sem->nblocked--;
  12.         if (sem->nblocked + sem->count < 0)
  13.         {    // this thread is not ready to be unblocked
  14.             goto _again;
  15.         }
  16.     }
  17.     pthread_mutex_unlock(sem->mutex);
  18. }

如果count不记录被阻塞的线程个数,以下方案很理想:

  1. sem_down(sem)
  2. {
  3.     pthread_mutex_lock(sem->mutex);
  4.     // critical section    
  5.     while(sem->count == 0)
  6.     {
  7.         pthread_cond_wait(sem->cond, sem->mutex); 
  8.     }
  9.     sem->count--;
  10.     pthread_mutex_unlock(sem->mutex);
  11. }

 

posted @ 2008-10-30 17:20  quanben  阅读(261)  评论(0编辑  收藏  举报