1.生产者-消费者问题
- 有m个生产者,有n个消费者,有count个缓冲区
- 生产者在生产产品放到缓冲区;消费者从缓冲区中拿走产品消费。
- 存在临界条件:生产者放入产品时,缓冲区满了,需要等待;缓冲区空了,消费者消费产品,需要等待
pc伪代码:
semaphore mutex;
semaphore blank=count;
semaphore fillcount=0;
produce()
{
while(true)
{
item=produceitem();
down(blank);
down(mutex)
putitemtobuffer(item);
up(mutex)
up(fillcount);
}
}
cosumer()
{
while(true)
{
down(fillcount);
down(mutex);
item=getitemfrombuffer();
up(mutex);
up(blank);
cosumeitem(item);
}
}
pc代码实现:
sem_t blank;
sem_t fillcount;
int buf[NUM];
static int p=0;
static int c=0;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
void *produce1(void *arg)
{
while(1)
{
sem_wait(&blank);//--操作
pthread_mutex_lock(&mutex);
buf[p]=rand();
printf("produce product:%d\n",buf[p]);
p=(p+1)%NUM;
pthread_mutex_unlock(&mutex);
sem_post(&fillcount);//++操作
sleep(1);
}
pthread_exit(NULL);
}
void *produce2(void *arg)
{
while(1)
{
sem_wait(&blank);//--操作
pthread_mutex_lock(&mutex);
buf[p]=rand();
printf("produce product:%d\n",buf[p]);
p=(p+1)%NUM;
pthread_mutex_unlock(&mutex);
sem_post(&fillcount);//++操作
sleep(1);
}
pthread_exit(NULL);
}
void *consumer1(void *arg)
{
while(1)
{
sem_wait(&fillcount);//--
pthread_mutex_lock(&mutex);
printf("consumer cosume:%d\n",buf[c]);
c=(c+1)%NUM;
pthread_mutex_unlock(&mutex);
sem_post(&blank);//++
sleep(1);
}
pthread_exit(NULL);
}
void *consumer2(void *arg)
{
while(1)
{
sem_wait(&fillcount);//--
pthread_mutex_lock(&mutex);
printf("consumer cosume:%d\n",buf[c]);
c=(c+1)%NUM;
pthread_mutex_unlock(&mutex);
sem_post(&blank);//++
sleep(1);
}
pthread_exit(NULL);
}
int main()
{
sem_init(&blank,0,NUM);//初始化成NUM
sem_init(&fillcount,0,0);
srand(time(NULL));
pthread_t tid;
int ret=0;
ret=pthread_create(&tid,NULL,produce1,NULL);
if(ret<0)
{
perror("pthread_create");
exit(0);
}
ret=pthread_create(&tid,NULL,produce2,NULL);
if(ret<0)
{
perror("pthread_create");
exit(0);
}
ret=pthread_create(&tid,NULL,consumer1,NULL);
if(ret<0)
{
perror("pthread_create");
exit(0);
}
ret=pthread_create(&tid,NULL,consumer2,NULL);
if(ret<0)
{
perror("pthread_create");
exit(0);
}
while(1)
{
sleep(2);
}
return 0;
}
2、哲学家就餐问题
- 5个哲学家,5根筷子,围坐在一个圆桌周围,平时,哲学家在思考,吃饭的时候,只有同时拿起左边和右边的筷子的哲学家才可以吃饭。
- 临界条件:当5个哲学家都争抢着吃饭时,可能出现这样的情况,每个哲学家都拿起了左边的筷子,那么就没有一个哲学家同时拿起左边和右边的筷子
- 如何避免出现临界条件?
- 规定:最多只允许4个哲学家同时拿起左边的筷子
philosoper伪代码:
semaphore chopstick[5]={1};
semaphore room=4;
philosopher(int i)
{
thinking();
wait(room);
wait(chopstick[i]);
wait(chopstick[(i+1)%5]);
eating();
signal(chopstick[i]);
signal(chopstick[(i+1)%5]);
signal(room);
}
philosoper代码实现:
sem_t room;
sem_t chip[5];
void *philosopher(void *arg)
{
int i=0;
i=*((int *)arg);
while(1)
{
printf("philosoper %d thinking\n",i);
sem_wait(&room);
sem_wait(&chip[i]);
sem_wait(&chip[(i+1)%5]);
printf("philosopher %d eating\n",i);
sem_post(&chip[(i+1)%5]);
sem_post(&chip[i]);
sem_post(&room);
sleep(2);
}
pthread_exit(NULL);
}
int main()
{
//信号量初始化
sem_init(&room,0,4);//最多只允许4个同时拿起左边的筷子
int i=0;
int arg[5]={0};
for(i=0;i<5;i++)
{
sem_init(chip+i,0,1);//5个筷子信号量,初始化为1
arg[i]=i;
}
int ret=0;
pthread_t tid;
for(i=0;i<5;i++)
{
ret=pthread_create(&tid,NULL,philosopher,(void *)&arg[i]);
if(ret<0)
{
perror("pthread_create");
exit(0);
}
}
while(1)
{
sleep(2);
}
pthread_join(tid,NULL);
return 0;
}
3.读者-写者问题
- m个读者在读文件,n个写者在写文件。
- 规定:读者可以同时读文件;写者不可以同时写文件;也不可以同时读文件和写文件
- 为了实现读者-写者问题,需要定义2把锁:读锁和写锁
rw伪代码:
semaphore rmutex;
semaphore wmutex;
down(wmutex)
writing
up(wmutex)
down(rmutex)
if(readcount==0)
{
down(wmutex)
}
readcount++
up(rmutex)
reading
down(rmutex)
readcount--
if(readcount==0)
{
up(wmutex)
}
up(rmutex)
rw代码实现:
sem_t rmutex;
sem_t wmutex;
int wnum=0;
int rnum=0;
int buf[3]={0};
void read()
{
}
void write()
{
wnum++;
int i=(wnum%3)+1;
printf("%d号写者在写",i);
sleep(2);
}
void *reader(void *arg)
{
while(1)
{
sem_wait(&rmutex);
if(rnum==0)
{
sem_wait(&wmutex);
}
rnum++;
sem_post(&rmutex);
read();
sem_wait(&rmutex);
rnum--;
if(rnum==0)
{
sem_post(&wmutex);
}
sem_post(&rmutex);
}
pthread_exit(NULL);
}
void *writer(void *arg)
{
while(1)
{
sem_wait(&wmutex);
write();
sem_post(&wmutex);
}
pthread_exit(NULL);
}
int main()
{
sem_init(&rmutex,0,1);
sem_init(&wmutex,0,1);
pthread_t tid;
int ret=0,i;
for(i=0;i<3;i++)
{
pthread_create(&tid,NULL,writer,NULL);
if(ret<0)
{
perror("pthread_create");
exit(0);
}
}
for(i=0;i<5;i++)
{
pthread_create(&tid,NULL,reader,NULL);
if(ret<0)
{
perror("pthread_create");
exit(0);
}
}
pthread_join(tid,NULL);
return 0;
}