以上两篇的思路是:锁定左边的筷子,然后去锁定右边的筷子,要是失败,就把左边的筷子也释放掉。如果不这样的话,万一4个哲学家都已经锁定了左边的筷子,然后最后一个人也锁定了左边的筷子,最后每个人都不释放左边的筷子,而右边的筷子是别人的左边筷子。这不就死锁了吗!但是,如果有一个人是先锁定右边再锁定左边,那么:
1:如果他的左边筷子被锁定,说明他的右边筷子已经锁定了,那就可以吃了,就不是死锁了。
2:如果他的左边筷子没有锁定,那么他左边那个人的右边筷子就可以用了啊,拿也不会死锁。
可以不只一个人,比如1,3是先左后右,0,2,4是先右后左。
先看死锁的代码:
#include <semaphore.h>
#include <stdio.h>
#include<errno.h>
#define N 5
#define M 10
int cholk[N];
sem_t st[N];
void *func(void *);
int main()
{
pthread_t person[N];
int i;
//init thread
for(i=0;i<N;i++)
{
sem_init(st+i,0,1);
}
// create N threads
for(i=0;i<N; i++)
{
if(pthread_create(person+i, NULL, func, (void*)i)!=0 )
{
fprintf(stderr, "create error\n");
exit(2);
}
}
//wait for thread terminal
for(i=0;i<N;i++)
{
pthread_join(*(person+i), NULL);
}
for(i=0;i<N;i++)
sem_destroy(st+i);
return 0;
}
void *func(void *p)
{
while(1)
{
int i=(int)p;
sem_wait(st+i);
sem_wait(st+(i+1)%N );
cholk[i]=i;
cholk[(i+1)%N]=i;
// usleep(100);
printf("The %d th person have dinner! %d,%d %s\n", i, cholk[i], cholk[(i+1)%N],
(cholk[i]==cholk[(i+1)%N] && cholk[i]==i) ? "right":"wrong" );
// after eat dinner, release both;
sem_post(st+i);
sem_post(st+(i+1)%N);
//usleep(100);
}
return NULL;
}
改掉以后不死锁的代码:
sem_wait(st+i);
sem_wait(st+(i+1)%N );
改成
if(i%2==1)
{
sem_wait(st+i);
sem_wait(st+(i+1)%N );
}else
{
sem_wait(st+(i+1)%N );
sem_wait(st+i);
}
cygwin上跑了半小时,没有死锁哦。