ENTRY PROTOCOL(for Process i ):
repeat {//从turn到i是否存在请求进程:若存在,则不断循环,直至不存在这样的进程,将当前进程标记为ACTIVE
flags[i] = WAITING;//表明自己需要资源
index = turn;//轮到谁了while (index != i) {//从turn到i轮流找不idle的线程if (flag[index] != IDLE) index = turn;//turn到i有非idle的阻塞else index = (index+1) mod n; //否则轮到i,并跳出
}
flags[i] = ACTIVE;//Pi active; 其他线程有可能active//对所有ACTIVE的进程做进一步的判断,判断除了当前进程以外,是否还存在其他ACTIVE的进程
index = 0;//看看是否还有其他active的while ((index < n) && ((index == i) || (flags[index] != ACTIVE))) {
index = index+1;
}//如果后面没有active了,并且轮到Pi或者turn idle, 就轮到i;否则继续循环
} until ((index >= n) && ((turn == i) || (flags[turn] == IDLE)));
turn = i;//获得turn并处理
N线程 - 离开临界区
EXIT PROTOCOL(for Process i ):
index = turn+1 mod n;//找到一个不idle的while (flags[index] == IDLE) {
index = index+1 mod n;
}
turn = index;//找到不idle的设置为turn;或者设置为自己
flag[i] = IDLE;//结束,自己变idle
提纲
背景
现实生活中的同步互斥
临界区
同步互斥的方法
4.1 禁用硬件中断
4.2 基于软件的解决方法
4.3 更高级的抽象方法
方法3:更高级的抽象方法
基于软件的解决方法
复杂,需要忙等待
更高级的抽象方法
硬件提供了一些同步原语
中断禁用,原子操作指令等
操作系统提供更高级的编程抽象来简化线程同步
例如:锁、信号量
用硬件原语来构建
锁(lock)
锁是一个抽象的数据结构
一个二进制变量(锁定/解锁)
使用锁来控制临界区访问
Lock::Acquire()
锁被释放前一直等待,后得到锁
Lock::Release()
释放锁,唤醒任何等待的线程
锁(lock)
现代CPU提供一些特殊的原子操作指令
原子操作指令
测试和置位(Test-and-Set )指令
从内存单元中读取值
测试该值是否为1(然后返回真或假)
内存单元值设置为1
输入0,改成1,返回0;
输入1,保持1,返回1;
锁(lock)
现代CPU都提供一些特殊的原子操作指令
do {
while(TestAndSet(&lock)) ;
critical section;
lock = false;
remainder section;
} while (true)
锁(lock)
现代CPU都提供一些特殊的原子操作指令
do {
while(TestAndSet(&lock)) ;
critical section;
lock = false;
remainder section;
} while (true)