“生产者/消费者”问题描述:
有一个有限缓冲区和两个线程:生产者和消费者。他们分别把产品放入缓冲区和从缓冲区中拿走产品。当一个生产者在缓冲区满时必须等待,当一个消费者在缓冲区空时也必须等待。
1. 单锁模型
- #include"stdio.h"
- #include"pthread.h"
- int buffer[10];
- int top = 0;
- int itime = 0;
- int itime2 = 0;
- pthread_t thread[2];
- pthread_mutex_t mut;
- void producer()
- {
- while(1)
- {
- if(itime == 10) return;
- pthread_mutex_lock(&mut);
- if(top == 10)
- {
- printf("buffer is full...producer is waiting...\n");
- pthread_mutex_unlock(&mut);
- continue;
- }
- printf("pruducter set the %d\n", itime);
- top++;
- itime++;
- pthread_mutex_unlock(&mut);
- }
- }
- void consumer()
- {
- while(1)
- {
- if(itime2 == 10) return;
- pthread_mutex_lock(&mut);
- if(top == 0)
- {
- printf("buffer is empty...consumer is waiting...\n");
- pthread_mutex_unlock(&mut);
- continue;
- }
- printf("consumer get the %d\n", itime2);
- top--;
- itime2++;
- pthread_mutex_unlock(&mut);
- }
- }
- int main()
- {
- pthread_create(&thread[0], NULL, (void*)(&producer), NULL);
- pthread_create(&thread[1], NULL, (void*)(&consumer), NULL);
- sleep(1);
- return 0;
- }
运行结果
- buffer is empty...consumer is waiting...
- buffer is empty...consumer is waiting...
- buffer is empty...consumer is waiting...
- pruducter set the 0
- pruducter set the 1
- pruducter set the 2
- pruducter set the 3
- pruducter set the 4
- pruducter set the 5
- pruducter set the 6
- pruducter set the 7
- pruducter set the 8
- pruducter set the 9
- consumer get the 0
- consumer get the 1
- consumer get the 2
- consumer get the 3
- consumer get the 4
- consumer get the 5
- consumer get the 6
- consumer get the 7
- consumer get the 8
- consumer get the 9
分析
容易出现极端状况,一开始一直是consumer加锁,producer无法提供;不久后producer终于得到加锁,存入了10个货物,而后consumer取得10个货物。
2. 两个互斥锁
- #include"stdio.h"
- #include"pthread.h"
- int buffer[10];
- int top = 0;
- int itime = 0;
- int itime2 = 0;
- pthread_t thread[2];
- pthread_mutex_t mut;
- pthread_mutex_t mut2;
- void producer()
- {
- while(1)
- {
- if(itime == 10) return;
- pthread_mutex_lock(&mut);
- if(top == 10)
- {
- printf("buffer is full...producer is waiting...\n");
- pthread_mutex_unlock(&mut2);
- continue;
- }
- printf("pruducter set the %d\n", itime);
- top++;
- itime++;
- pthread_mutex_unlock(&mut2);
- }
- }
- void consumer()
- {
- while(1)
- {
- if(itime2 == 10) return;
- pthread_mutex_lock(&mut2);
- if(top == 0)
- {
- printf("buffer is empty...consumer is waiting...\n");
- pthread_mutex_unlock(&mut);
- continue;
- }
- printf("consumer get the %d\n", itime2);
- top--;
- itime2++;
- pthread_mutex_unlock(&mut);
- }
- }
- int main()
- {
- pthread_create(&thread[0], NULL, (void*)(&producer), NULL);
- pthread_create(&thread[1], NULL, (void*)(&consumer), NULL);
- sleep(1);
- return 0;
- }
运行结果
- buffer is empty...consumer is waiting...
- pruducter set the 0
- consumer get the 0
- pruducter set the 1
- consumer get the 1
- pruducter set the 2
- consumer get the 2
- pruducter set the 3
- consumer get the 3
- pruducter set the 4
- consumer get the 4
- pruducter set the 5
- consumer get the 5
- pruducter set the 6
- consumer get the 6
- pruducter set the 7
- consumer get the 7
- pruducter set the 8
- consumer get the 8
- pruducter set the 9
- consumer get the 9
很完美对不对?生产者生产一个就把自己锁起来,消费者消费一个后解锁生产者,把自己锁起来,生产者继续生产,循环反复。互斥锁的确能很好的实现进程/线程之间的同步问题,但是它是通过锁机制来实现的,就是仅仅通过加锁和解锁实现同步,效率比较低。
3. 利用条件变量
- #include"stdio.h"
- #include"pthread.h"
- int buffer[10];
- int top = 0;
- int itime = 0;
- int itime2 = 0;
- pthread_t thread[2];
- pthread_mutex_t mut;
- pthread_cond_t con, con2;
- void producer()
- {
- while(1)
- {
- if(itime == 10) return;
- pthread_mutex_lock(&mut);
- if(top == 10)
- {
- printf("buffer is full...producer is waiting...\n");
- pthread_cond_wait(&con, &mut);
- }
- printf("pruducter set the %d\n", itime);
- top++;
- itime++;
- pthread_cond_signal(&con2);
- pthread_mutex_unlock(&mut);
- sleep(1);
- }
- }
- void consumer()
- {
- while(1)
- {
- if(itime2 == 10) return;
- pthread_mutex_lock(&mut);
- if(top == 0)
- {
- printf("buffer is empty...consumer is waiting...\n");
- pthread_cond_wait(&con2, &mut);
- }
- printf("consumer get the %d\n", itime2);
- top--;
- itime2++;
- pthread_cond_signal(&con);
- pthread_mutex_unlock(&mut);
- sleep(1);
- }
- }
- int main()
- {
- pthread_create(&thread[0], NULL, (void*)(&producer), NULL);
- pthread_create(&thread[1], NULL, (void*)(&consumer), NULL);
- sleep(10);
- return 0;
- }
运行结果
- buffer is empty...consumer is waiting...
- pruducter set the 0
- consumer get the 0
- buffer is empty...consumer is waiting...
- pruducter set the 1
- consumer get the 1
- buffer is empty...consumer is waiting...
- pruducter set the 2
- consumer get the 2
- buffer is empty...consumer is waiting...
- pruducter set the 3
- consumer get the 3
- pruducter set the 4
- consumer get the 4
- pruducter set the 5
- consumer get the 5
- pruducter set the 6
- consumer get the 6
- pruducter set the 7
- consumer get the 7
- pruducter set the 8
- consumer get the 8
- pruducter set the 9
- consumer get the 9
结果还算比较正常,理解一下变量的使用。消费者发现缓冲区没有东西,通过条件变量把自己锁住;生产者生产并激活消费者;消费者从缓冲区消费;当生产者发现缓冲区满的时候,通过条件变量把自己锁住,消费者消费并重新激活生产者。如此。