Unix高级环境编程系列笔记(3)

发表于:2013-11-18来源:IT博客大学习作者:nebula点击数: 标签:Unix
加锁与解锁: #include int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); All return: 0

  加锁与解锁:

  #include

  int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

  int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

  int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

  All return: 0 if OK, error number on failure

  对于读者的数量会有限制,因此调用 pthread_rwlock_rdlock时需要检查返回值。

  在正确使用的情况下,不需要检查pthread_rwlock_wrlock和pthread_rwlock_unlock的返回值。

  条件加锁:

  #include

  int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

  int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

  Both return: 0 if OK, error number on failure

  10.什么是条件变量,它有什么作用?

  条件变量是线程可用的另外一种同步机制。条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定条件的发生。条件本身是由互斥量保护的。线程在改变状态前必须首先锁住互斥量,其它线程在获得互斥量之前不会觉察到这种变化。

  11.如何使用条件变量?

  条件变量的类型为pthread_cond_t ,其初始化与销毁的方式与mutex类似,注意静态变量可以通过指定常量PTHREAD_COND_INITIALIZER来进行初始化。

  #include

  int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);

  int pthread_cond_destroy(pthread_cond_t *cond);

  Both return: 0 if OK, error number on failure

  使用pthread_cond_wait来等待条件变成真。

  函数定义如下:

以下是代码片段:
#include 
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond,  pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);

Both return: 0 if OK, error number on failure
调用者把锁住的mutex传递给pthread_cond_wait,函数把调用线程放到等待条件变量的线程列表上,然后对互斥量解锁,这两个操作是原子操作。这样就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间窗口。pthread_cond_wait返回时,mutex会再次被锁住。

  注意,调用成功返回后,线程需要重新计算条件变量,因为其它线程可能已经改变了条件。

  有两个函数用于通知线程一个条件已经被满足。pthread_cond_signal函数用来唤醒一个等待条件满足的线程, pthread_cond_broadcast用来唤醒所有等待条件满足的线程。

  他们的定义为:

  #include

  int pthread_cond_signal(pthread_cond_t *cond);

  int pthread_cond_broadcast(pthread_cond_t *cond);

  Both return: 0 if OK, error number on failure

  下面的这段代码实现了类似于生产者消费者模型的程序,生产者通过enqueue_msg将消息放入队列,并发送信号通知给消费者线程。消费者线程被唤醒然后处理消息。

  #include

  struct msg {

  struct msg *m_next;

  /* ... more stuff here ... */

  };

  struct msg *workq;

  pthread_cond_t qready = PTHREAD_COND_INITIALIZER;

  pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;

  void

  process_msg(void)

  {

  struct msg *mp;

  for (;;) {

  pthread_mutex_lock(&qlock);

  while (workq == NULL)

  pthread_cond_wait(&qready, &qlock);

  /*get msg from the queue*/

  mp = workq;

  workq = mp->m_next;

  pthread_mutex_unlock(&qlock);

  /* now process the message mp */

  }

  }

  void

  enqueue_msg(struct msg *mp)

  {

  pthread_mutex_lock(&qlock);

  /*put msg in queue*/

  mp->m_next = workq;

  workq = mp;

  pthread_mutex_unlock(&qlock);

  pthread_cond_signal(&qready);

  }

  在pthread_cond_signal发送消息之前并不需要占用锁,因为一旦线程被唤醒后通过while发现没有要处理的msg存在则会再次陷入睡眠。如果系统不能容忍这种竞争环境,则需要在unlock之前调用cond_signal,但是在多处理器机器上,这样会导致多线程被唤醒然后立即进入阻塞(cond_signal唤醒线程,但由于我们仍占用着锁,所以这些线程又会立即阻塞)。

原文转自:http://blogread.cn/it/article/3344