并发需要解决的问题是死锁和饥饿。
解决办法是检测,预防和避免。
6.1 死锁的原理
进程A和进程B都需要资源X和Y才能完成,但进程A占有了资源X,进程B占有了资源Y。都等待对方释放,导致两个进程都无法执行,出现死锁。
进程A需要资源X才能执行,但进程B在占用资源X时,被打断,优先级更高的进程A开始执行。也会导致死锁。
6.6 哲学家就餐问题
5个哲学家,只有5把叉子。避免死锁和饥饿。
6.7 UNIX的并发机制
6.7.1 管道
管道是一个环形缓冲区,让2个进程以消费者和生产者的模型通信。一个进程写,一个进程读。
函数:cwait,csignal
fork_ready[5]
fork[5]={true}
void get_forks(int pid)
{
left =pid
right = ++pid %5;
// 获取左边
if(!fork[left])
cwait(fork_ready[left]); // queue 等待释放
fork[left]=false;
// 获取右边
if(!fork[rigth])
cwait(fork_ready[right]); // queue 等待释放
fork[right]=false;
}
void release_forks(int pid)
{
left =pid
right = ++pid %5;
// 释放左边
if(empty(fork_ready[left])) // 没有人在这个管道上等待
fork_ready[left] = ture; // 可以直接修改状态
else
csignal(fork_ready[left]) // 有人等待,通过管道触发解除等待
// 释放右边
if(empty(fork_ready[right]))
fork_ready[right] = ture;
else
csignal(fork_ready[right])
}
6.7.2 消息
有类型的一段文本,msgsnd和msgrcv。每个进程都有与之相关的消息队列。