“生产者/消费者”问题描述:
有一个有限缓冲区和两个线程:生产者和消费者。他们分别把产品放入缓冲区和从缓冲区中拿走产品。当一个生产者在缓冲区满时必须等待,当一个消费者在缓冲区空时也必须等待。
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
结果还算比较正常,理解一下变量的使用。消费者发现缓冲区没有东西,通过条件变量把自己锁住;生产者生产并激活消费者;消费者从缓冲区消费;当生产者发现缓冲区满的时候,通过条件变量把自己锁住,消费者消费并重新激活生产者。如此。