pthread_cond_wait

下面说一下,pthread_cond_wait(&mycond,&mymutex)的东西
1. 设计pthread_cond_wait 的初衷
   线程如果需要等待某个条件发生,它该作何处理呢?它可以重复对互斥对象锁定和解锁,每次都会检查共享元素,以查找某个值。这样会比较浪费cpu的时钟周 期。而且效率比较低,何不借鉴一下dma的处理办法,等待某个条件发生了通知一下,这样cpu就可以处理自己的事了,我想 pthread_cond_wait的初衷就是这样的,也是这样被设计出来的。如果你有不同解释可以通知我,我们可以共同讨论。
2. pthread_cond_wait的内部操作
   在调用之前需要锁定互斥对象,然后再调用pthread_cond_wait。
  1> pthread_cond_wait所做的第一件事就是同时对互斥对象解锁(这样其它线程就可以修改共享对象了,操作之前不要忘记加锁哦)。
  2> 等待条件通常是一个阻塞操作(这一点有点不明白,为什么是通常,难道说是还有其它动作,有知道的可以告诉我啊),这意味着线程将睡眠,在它苏醒之前不会消 耗cpu周期(这正是我们想要的).线程睡呀睡呀,直到,有人叫它, 比如:另一个线程锁定了mymutex,并对共享对象对了某个动作.在对互斥对象解锁之后(this is very important),2号线程会立即调用函数pthread_cond_broadcast(&mycond)(这个地方也有点不明白, 我想不一定需要立即调用pthread_cond_broadcast,日比如有一个共享的线程数目 pthread_num = 5,当创建一个线程的时候pthread_num++,但是当该线程结束的时候pthread_num--,如果这个数小于5,我们就可以广播一下这个事 件,激活一个线程,用以创建更多的线程)。
  3> 调用pthread_cond_wait的线程被叫醒之后,将重新锁定mymutex,之后才返回。

 

下面画个图来表示一下期间锁的调用(是伪码)
lock(mutex)   ----------------a.lock
pthread_cond_wait()
{
    unlock(mutex)-------------a.unlock
    if ( 条件不满足)
      睡觉
    else
    {
      lock(mutex)-------------b.lock
      return
    }
}
dosomething();
unlock(mutex);---------------b.unlock

 

条件锁和互斥锁不同

个人理解:

互斥锁:n个同等关系的线程竞争资源

条件锁:虽然也是彼此竞争资源,但是某些线程在一定条件下才会去竞争资源,如果条件不满足则挂起。这个"一定条件“则由条件锁来控制。

下面这个例子举例说明条件锁:1个生产者,3个消费者。3个消费者彼此是同类型的竞争关系,生产者也会去竞争,但是必须满足一定条件(产品消耗完了)被通知后才会去竞争。

从实验结果来看生产者和消费者竞争时没有任何优势,得到锁的概率是同等的。

#include <stdio.h>
#include <pthread.h>

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static const int THREAD_COUNT = 3;//3个消费者

static int resources = 0;

static void* thread_func(void* arg) {
    while (1) {
        pthread_mutex_lock(&mtx);
        if (!resources) {
            printf("get lock resource 0\n"); pthread_cond_signal(
&cond); } else { resources--; //消费一个资源 printf("Tid 0x%x: Consume a resource, rest resources:%d\n", (int)pthread_self(), resources); } pthread_mutex_unlock(&mtx); sleep(1); //这一行去掉会影响锁的竞争 } } void main() { pthread_t tid; int i; for (i = 0; i < THREAD_COUNT; i++) { pthread_create(&tid, NULL, thread_func, NULL); } sleep(2); while (1) { // 这里最好不要sleep,因为资源随时可能被消费完,这时我们需要第一时间生产资源 pthread_mutex_lock(&mtx); pthread_cond_wait(&cond, &mtx); resources += 10;//生产者一次增加10个资源,然后进入下次循环挂起 printf("main thread: add 10 resources\n"); pthread_mutex_unlock(&mtx); } }

muhe221@muhe:~/Downloads$ gcc -o consume.o consume.c -lpthread
muhe221@muhe:~/Downloads$ ./consume.o
main thread: add 10 resources
Tid 0x9f93b700: Consume a resource, rest resources:9
Tid 0xa093d700: Consume a resource, rest resources:8
Tid 0xa013c700: Consume a resource, rest resources:7
Tid 0x9f93b700: Consume a resource, rest resources:6
Tid 0xa093d700: Consume a resource, rest resources:5
Tid 0xa013c700: Consume a resource, rest resources:4
Tid 0x9f93b700: Consume a resource, rest resources:3
Tid 0xa093d700: Consume a resource, rest resources:2
Tid 0xa013c700: Consume a resource, rest resources:1
Tid 0xa093d700: Consume a resource, rest resources:0
main thread: add 10 resources
Tid 0xa013c700: Consume a resource, rest resources:9
Tid 0x9f93b700: Consume a resource, rest resources:8
Tid 0xa093d700: Consume a resource, rest resources:7
Tid 0xa013c700: Consume a resource, rest resources:6
Tid 0x9f93b700: Consume a resource, rest resources:5
Tid 0xa093d700: Consume a resource, rest resources:4
Tid 0xa013c700: Consume a resource, rest resources:3
Tid 0x9f93b700: Consume a resource, rest resources:2
Tid 0xa093d700: Consume a resource, rest resources:1
Tid 0xa013c700: Consume a resource, rest resources:0
main thread: add 10 resources
Tid 0xa013c700: Consume a resource, rest resources:9
Tid 0xa093d700: Consume a resource, rest resources:8

pthread_cond_wait(&cond, &mtx);等到条件满足后一定能抢到mtx锁吗?不一定。但是迟早能抢到锁。
去掉sleep(1)测试结果如下
............
get lock resource 0
main thread: add 10 resources
Tid 0xe07ea700: Consume a resource, rest resources:9
Tid 0xe17ec700: Consume a resource, rest resources:8
Tid 0xe0feb700: Consume a resource, rest resources:7
Tid 0xe07ea700: Consume a resource, rest resources:6
Tid 0xe07ea700: Consume a resource, rest resources:5
Tid 0xe07ea700: Consume a resource, rest resources:4
Tid 0xe07ea700: Consume a resource, rest resources:3
Tid 0xe07ea700: Consume a resource, rest resources:2
Tid 0xe07ea700: Consume a resource, rest resources:1
Tid 0xe0feb700: Consume a resource, rest resources:0
get lock resource 0
get lock resource 0
get lock resource 0
main thread: add 10 resources
Tid 0xe07ea700: Consume a resource, rest resources:9
Tid 0xe17ec700: Consume a resource, rest resources:8
Tid 0xe07ea700: Consume a resource, rest resources:7
Tid 0xe0feb700: Consume a resource, rest resources:6
Tid 0xe07ea700: Consume a resource, rest resources:5
posted @ 2015-11-07 15:24  牧 天  阅读(187)  评论(0)    收藏  举报