多线程

转载 2011年10月17日 10:47:01
 

Linux下面的线程锁,条件变量以及信号量的使用

一) 线程锁
1) 只能用于"锁"住临界代码区域
2) 一个线程加的锁必须由该线程解锁.

锁几乎是我们学习同步时最开始接触到的一个策略,也是最简单, 最直白的策略.

二) 条件变量,与锁不同, 条件变量用于等待某个条件被触发
1) 大体使用的伪码:

// 线程一代码
pthread_mutex_lock(&mutex);
// 设置条件为true
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

// 线程二代码
pthread_mutex_lock(&mutex);
while (条件为false)
    pthread_cond_wait(&cond, &mutex);
修改该条件
pthread_mutex_unlock(&mutex);

需要注意几点:
1) 第二段代码之所以在pthread_cond_wait外面包含一个while循环不停测试条件是否成立的原因是, 在pthread_cond_wait被唤醒的时候可能该条件已经不成立.UNPV2对这个的描述是:"Notice that when pthread_cond_wait returns, we always test the condition again, because spurious wakeups can occur: a wakeup when the desired condition is still not true.".

2) pthread_cond_wait调用必须和某一个mutex一起调用, 这个mutex是在外部进行加锁的mutex, 在调用pthread_cond_wait时, 内部的实现将首先将这个mutex解锁, 然后等待条件变量被唤醒, 如果没有被唤醒, 该线程将一直休眠, 也就是说, 该线程将一直阻塞在这个pthread_cond_wait调用中, 而当此线程被唤醒时, 将自动将这个mutex加锁.
man文档中对这部分的说明是:
pthread_cond_wait atomically unlocks the mutex (as per pthread_unlock_mutex) and waits for the condition variable cond to  be  signaled.  The thread execution is suspended and does not consume any CPU time until the condition variable is
signaled. The mutex must be locked by the calling thread on entrance to pthread_cond_wait.  Before  returning  to  the calling thread, pthread_cond_wait re-acquires mutex (as per pthread_lock_mutex).
也就是说pthread_cond_wait实际上可以看作是以下几个动作的合体:
解锁线程锁
等待条件为true
加锁线程锁.

这里是使用条件变量的经典例子:
http://www.cppblog.com/CppExplore/archive/2008/03/20/44949.html
之所以使用两个条件变量, 是因为有两种情况需要进行保护,使用数组实现循环队列,因此一个条件是在getq函数中判断读写指针相同且可读数据计数为0,此时队列为空没有数据可读,因此获取新数据的条件变量就一直等待,另一个条件是读写指针相同且可读数据计数大于0,此时队列满了不能再添加数据, 因此添加新数据的条件变量就一直等待,而nEmptyThreadNum和nFullThreadNum则是计数, 只有这个计数大于0时才会唤醒相应的条件变量,这样可以减少调用pthread_cond_signal的次数.
为了在下面的叙述方便, 我将这段代码整理在下面, 是一个可以编译运行的代码,但是注意需要在编译时加上-pthread链接线程库:
收藏助手
不良信息举报
您举报文章:多线程
举报原因:
原因补充:

(最多只允许输入30个字)