@yanglt7
2018-05-22T07:31:39.000000Z
字数 4470
阅读 1024
操作系统
9.1 背景
9.2 现实生活中的同步问题
相互感知的程度 | 交互关系 | 进程间的影响 |
---|---|---|
相互不感知(完全不了解其他进程的存在) | 独立 | 一个进程的操作催其他进程的结果无影响 |
间接感知(双方都与第三方交互,如共享资源) | 通过共享进行协作 | 一个进程的结果依赖于共享资源的状态 |
直接感知(双方直接交互,如通信) | 通过通信进行协作 | 一个进程的结果依赖于从其他进程获得的信息 |
9.3 临界区(critical section)
9.4 禁用硬件中断
没有中断,没有上下文切换,因此没有并发,整个系统由当前进程独占
现代计算机体系结构都提供指令来实现禁用中断
进入临界区
禁止所有中断,并保存标志
离开临界区
禁用中断中,进程无法被停止
临界区可能很长
要小心使用
9.5 基于软件的同步方法
int turn = 0
turn == i//表示允许进入临界区的线程
do {
while (turn != i);//条件不成立就可以进入临界区
critical section
trun = j;
remainder section
} while (1);
int flag[2];
flag[0] = flag[1] = 0;
flag[i] == 1;//表示线程Ti是否在临界区
do {
while (flag[j] == 1);
flag[i] = 1;
critical section
flag[i] = 0;
remainder section
} while (1);
int flag[2];
flag[0] = flag[1] = 0;
flag[i] == 1;//表示线程Ti想要进入临界区
do {
flag[i] = 1;
while (flag[j] == 1);
critical section
flag[i] = 0;
remainder section
} whlie (1);
int turn;
boolean flag[];//表示进程是否准备好进入临界区
flag[i] = true;
turn = j;
while (flag[j] && turn ==j) //两个条件只要一个不满足就能进去
flag[i] = false;
do {
flag[i] = true;
turn = j;
while (flag[j] && turn == j);
critical section
flag[i] = false;
remainder section
} while (1);
flag[0] := false;
flag[1] := false;
turn := 0;//orl
do {
flag[i] = true;
while flag[j] == true {
if turn != i {
flag[i] := false
while turn != i{}
flag[i] := true
}
}
critical section
turn := j
flag[i] = false;
remainder section
} while (true);
turn | i-1 | i | i+1 | i+2 | n-1 | 0 | ||
---|---|---|---|---|---|---|---|---|
处理循环 | 处理循环 | 处理循环 | 处理循环 | 处理循环 | 处理循环 | 处理循环 | 处理循环 | 处理循环 |
线程Ti退出时,把turn改成下一个请求进程
特点:
复杂:
需要忙等待
9.6 更高级的抽象方法
硬件提供了一些同步原语
操作系统提供更高级的编程抽象来简化进程同步
锁是一个抽象的数据结构
Lock :: Acquire()
Lock :: Release()
使用锁来控制临界区访问
lock_next_pid -> Acquire();
new_pid = next_pid++;
lock_next_pid -> Release();
测试和置位(Test-and-Set)指令
交换指令(exchange)
class Lock {
int value = 0;//初始化锁里的初值为0
}
Lock :: Acquire() {
while (test-and-set(value));//spin
//构造它的请求操作原语,即用TS指令去把value的值读出来,并且往里写1。
//如果是1,则这个操作就相当于是个检查,如果是0,则设为1,循环结束。
}
如果锁被释放,那么TS指令读取0并将值设置1
如果锁处于忙状态,那么TS指令读取1并将值设置为1
Lock :: Release() {
value = 0;
}
Lock :: Acquire() {
while (test-and-set(value));//spin
}
Lock :: Release() {
value = 0;
}
class Lock {
int value = 0;
WaitQueue q;//在锁的数据结构里加上一个等待队列,即等待这个锁的相应的进程所排的队列
}
Lock :: Acquire() {
while (test-and-set(value));{
and this TCB to wait queue q;
schedule();
}
}
Lock :: Release() {
value = 0;//表示释放锁
remove one thread t from q;
wakeup(t);//将线程从等待队列放到就绪队列。等待时,就处于放弃CPU使用权的状态,实现了让权等待
}
优点
缺点
锁是一种高级的同步抽象方法
常用的三种同步实现方法