今日看19年的408的哲学家吃饭问题,对同步锁的位置有些困惑,与生产消费者的锁的问题是刚好相反的。
比如19年的题
有n(n≥3)位哲学家围坐在一张圆桌边,每位哲学家交替地就餐和思考。在
圆桌中心有m(m≥1)个碗,每两位哲学家之间有一根筷子。每位哲学家必须取到一个碗和两
侧的筷子后,才能就餐,进餐完毕,将碗和筷子放回原位,并继续思考。为使尽可能多的哲学
家同时就餐,且防止出现死锁现象,请使用信号量的P、V 操作[wait()、signal()操作]描述上
述过程中的互斥与同步,并说明所用信号量及初值的含义。
semaphore mutex=(n-1)<m ? n-1 :m ; 锁取 n-1和m的最下值
semaphore kuaizi[n] ; 筷子资源 第i位哲学家 旁边的筷子分别为 kuaizi[i],kuaizi[(i+1)%n] 0<=i<=n-1
for (int i=0;i<n;i++)
kuaizi[i]=1; //筷子全部置1
semaphore wan=m; 碗资源
void eat(int i) //哲学家i的吃饭流程
{
while(TRUE)
{
p(mutex); //准许进入吃饭
P(wan); //取得碗
P(kuaizi[i]); //取左边筷子
P(kuaizi[(i+1)%n]); //取右边筷子
吃饭;
V(kuaizi[i]);
V(kuaizi[(i+1)%n])
V(wan)
V(mutex);
}
}
这里的锁资源是放在进入拿资源的前面
只要在拿筷子前面就OK
而如果是生产者消费者问题
可以发现
ar items = 0, space = 10, mutex = 1;
var in = 0, out = 0;
item buf[10] = { NULL };
producer {
while( true ) {
P( space ); // 等待缓冲区有空闲位置, 在使用PV操作时,条件变量需要在互斥锁之前
P( mutex ); // 保证在product时不会有其他线程访问缓冲区
// product
buf.push( item, in ); // 将新资源放到buf[in]位置
in = ( in + 1 ) % 10;
V( mutex ); // 唤醒的顺序可以不同
V( items ); // 通知consumer缓冲区有资源可以取走
}
}
consumer {
while( true ) {
P( items ); // 等待缓冲区有资源可以使用
P( mutex ); // 保证在consume时不会有其他线程访问缓冲区
// consume
buf.pop( out ); // 将buf[out]位置的的资源取走
out = ( out + 1 ) % 10;
V( mutex ); // 唤醒的顺序可以不同
V( space ); // 通知缓冲区有空闲位置
}
}
锁是在最里面的
如果锁在最外面 ,那么如果 进入锁之后 ,如果直接为空 ,直接死锁。。
这就是完全没有联系的问题。。。。。。不要纠结了