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

浙公网安备 33010602011771号