进程在单处理机多道环境中,进程被交替执行,表现出并发性的特征。
怎样保证进程执行结果的正确性?
交互方式:
进程之间互相都不知道对方的存在(竞争关系)
进程之间间接知道对方(共享合作)
进程之间知道对方存在(通信合作)
进程之间交互关系:互斥 同步 通信
同步:指多个进程中发生的事件存在着某种时序关系,它们必须按规定时序执行,以共同完成一项任务。
互斥:多个进程不能同时使用统一资源。
临界资源:某段时间内仅允许一个进程使用的资源。如:打印机
临界区:每个进程中访问临界资源的那段代码。
同步机制应遵循的准则:
空闲让进
忙则等待
有限等待
让权等待
互斥实现的硬件方法:
禁止中断
专用机器指令:
TS(Test and Set)指令
Swap指令
TS(Test and Set)指令
//TS 指令:
boolean TS(lock);
boolean lock;
{ boolean temp;
temp = lock;
lock = true;
return temp;
}
//TS指令的使用
while(TS(lock))
/*什么也不做*/;
临界区;
lock = false;
剩余区;
Lock 有两种状态:
当lock = false时,表示资源空闲;
当lock = true时,表示资源正在被使用。
为了实现互斥,设布尔变量lock,其初值为false,表示资源空闲。利用TS指令实现互斥。
优点:适用范围广 简单 支持多个临界区
缺点:没有做到“让权等待”
1.单标志算法
//进程0
while(turn != 0){}
//什么都不做;
临界区;
turn = 1;
剩余区;
//进程1
while(turn != 1){}
//什么都不做;
临界区;
turn = 0;
剩余区;
设置公共整形变量turn,使P0、P1轮流访问临界资源。
缺点:强制性轮流进入临界区,不能保证“空闲让进”。
2.双标志、先检查算法
//进程0
while(flag[1]){}
//什么都不做;
flag[0] = true;
临界区;
flag[0] = false;
剩余区;
//进程1
while(flag[0]){}
//什么都不做;
flag[1] = true;
临界区;
flag[1] = false;
剩余区;
设置数组flag,初始时设每个元素为false,表示所有进程都未进入临界区。若flag[i] = true,表示进程进入临界区执行。解决了“空闲让进”问题。
缺点:可能同时进入临界区,不能保证“忙则等待”。
3.双标志、先修改后检查算法
//进程0
flag[0] = true;
while(flag[1]){}
//什么都不做;
临界区;
flag[0] = false;
剩余区;
//进程1
flag[1] = true;
while(flag[0]){}
//什么都不做;
临界区;
flag[1] = false;
剩余区;
两个进程先后同时做 flag[i] = true;
缺点:保证了不同时进入临界区,但又可能都进不去。不能保证“有空让进”。
4.先修改、后检查、后修改算法
//进程0
flag[0] = true;
turn = 1;
while(flag[1] && (turn == 1){}
//什么也不做
临界区;
flag[0] = false;
剩余区;
//进程1
flag[1] = true;
turn = 0;
while(flag[0] && (turn == 0){}
//什么也不做
临界区;
flag[1] = false;
剩余区;
保证了“有空让进”和“忙则等待”
现实生活中用解决信号量及PV操作解决临界资源互斥问题。
信号量的P操作:
void wait(semaphore s) {
s.value = s.value - 1;
if (s.value < 0)
block(s.queue);
/*将进程阻塞,并将其投入等待队列s.queue*/
}
信号量的V操作:
void signal(semaphore s) {
s.value = s.value + 1;
if (s.value <= 0)
wackup(s.queue);
/*唤醒阻塞进程,将其从等待队列s.queue取出,投入就绪队列*/
}
信号灯的物理意义:
从资源的观点看信号灯的意义:
s.value的初值表示系统中某种资源的数目
wait(s)表示要申请一个资源
signal(s)表示要释放一个资源
s.value<0时,|s.value|表示等待队列的进程数
用信号灯解决互斥问题:
semaphore mutex = 1;
P1:
while (1) {
P(mutex);
临界区;
V(mutex);
剩余区;
}
P2:
while (1) {
P(mutex);
临界区;
V(mutex);
剩余区;
}
用信号灯解决同步问题:
semaphore a,b = 0,0;
{s1 ; V(a) ; V(b)}
{P(a) ; s2}
{P(b) ; s3}
经典进程同步问题:
生产者——消费者问题(先操作资源变量 后操作互斥变量)
读者——写者问题
哲学家进餐问题
打瞌睡的理发师问题
解决多个信号量的死锁问题
管程机制
一个管程定义了一个数据结构和能为并发进程所执行(在该数据结构上)的一组操作,这组操作能同步进程和改变管程中的数据。
管程=数据结构+操作+对数据结构中变量的初始化
利用管程解决生产者-消费者问题
低级通信方式:
信号灯(效率低、通信对用户不透明
高级通信方式:
共享存储器系统、消息传递系统(直接通信 间接通信)、管道通信
通信链路的建立方式:
显示建立链路
隐式建立链路
通信方向:
(全双工、半双工)
通信链路连接方式:
(点对点)
通信链路的容量:
(无容量就是没有缓冲区)
数据格式:
字节流、报文
同步方式:
阻塞方式 不阻塞方式
客户-服务器系统通信:
命名管道 套接字 远程过程调用
总结
1.进程与线程
(1)进程引入的原因: 单道顺序执行、多道并发执行
(2)进程的状态与组成:进程的三种、五种、七种状态 进程控制块(PCB)
(3)进程的控制:创建、撤消;阻塞、唤醒;挂起、激活
(4)线程:线程控制块(TCB)
2.进程的同步与通信
(1)进程同步与互斥:并发、临界资源与临界区、软硬件实现互斥、信号量和PV操作
(2)经典进程同步问题:生产者消费者、读者写者、哲学家进餐、理发师(关键步骤之前用P,关键步骤之后用V)
(3)AND信号量
(4)管程:管程结构和思想(封装)、线程可临时放弃管程的互斥访问同步机制都被限制在管程内、三种队列(紧急、条件、入口)
(5)进程的通信:高级通信、低级通信;共享存储器、消息传递、管道方式