个人主页: 叶落闲庭
我的专栏:
c语言
数据结构
javaEE
操作系统
Redis
石可破也,而不可夺坚;丹可磨也,而不可夺赤。
进程具有异步性的特征。异步性是指,各并发执行的进程以各自独立的、不可预知的速度向前推进。
读进程和写进程并发地运行,由于并发必然导致异步性,因此“数据”和“读数据”两个操作执行的先后顺序是不确定的。而实际应用中,又必须按照“写数据→读数据”的顺序来执行的,如何解决这种异步问题,就是“进程同步”所讨论的内容。
同步亦称直接制约关系,它是指为完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上协调它们的工作次序而产生的制约关系。进程间的直接制约关系就是源于它们之间的相互合作。
do {
entry section; //进入区
critical section; //临界区
exit section; //退出区
remainder section; //剩余区
} while (true)
int turn = 0; //turn表示当前允许进入临界区的进程号
P0进程:
while (turn != 0); //①进入区
critical section; //②临界区
turn= 1; //③退出区
remainder section; //④剩余区
P1进程:
while (turn!= 1); //⑤进入区
critical section; //⑥临界区
turn= 0; //⑦退出区
remainder section; //⑧剩余区
turn的初值为0,即刚开始只允许0号进程进入临界区。
若P1先上处理机运行,则会一直卡在⑤。直到P1的时间片用完,发生调度,切换P0上处理机运行。
代码①不会卡住P0,P0可以正常访问临界区,在P0访问临界区期间即使切换回P1,P1依然会卡在⑤。
只有P0在退出区将turn改为1后,P1才能进入临界区。
flag[0]=true
”意味着0号进程P0现在想要进入临界区。每个进程在进入临界区之前先检查当前有没有别的进程想进入临界区,如果没有,则把自身对应的标志flag[i]
设为true,之后开始访问临界区。bool flag[2]; //表示进入临界区意愿的数组
flag[0] = false;
falg[1] = false; //刚开始设置为两个进程都不想进入临界区
P0进程:
while (falg[1]); //①
falg[0] = true; //②
critical section; //③
flag[0] = false; //④
remainder section;
P1进程:
while (flag[0]); //⑤ 如果此时P0想进入临界区,P1就一直循环等待
flag[1] = true; //⑥ 标记为P1进程想要进入临界区
critical section; //⑦ 访问临界区
flag[1] = false; //⑧ 访问完临界区,修改标记为P1不想使用临界区
remainder section;
bool flag[2]; //表示进入临界区意愿的数组
flag[0] = false;
falg[1] = false; //刚开始设置为两个进程都不想进入临界区
P0进程:
falg[0] = true; //①
while (falg[1]); //②
critical section; //③
flag[0] = false; //④
remainder section;
P1进程:
flag[1] = true; //⑤ 标记为P1进程想要进入临界区
while (flag[0]); //⑥ 如果此时P0想进入临界区,P1就一直循环等待
critical section; //⑦ 访问临界区
flag[1] = false; //⑧ 访问完临界区,修改标记为P1不想使用临界区
remainder section;
bool flag[2]; //表示进入临界区意愿的数组,初始值都是false
int turn = 0; //turn 表示优先让哪个进程进入临界区
P0进程:
flag[0] = true;
turn = 1;
while (flag[1] && turn == 1);
cirtical section;
flag[0] = false;
remainder section;
P1进程:
flag[1] = true;
turn = 0;
while (flag[0] && turn == 0);
cirtical section;
flag1] = false;
remainder section;
//布尔型共享变量lock表示当前临界区是否被加锁
//true表示已加锁,false表示未加锁
bool TestAndSet (bool *lock) {
bool old;
old = *lock; //old用来存放lock原来的值
*lock = true; //无论之前是否已加锁,都将lock设为true
return old; //返回lock原来的值
}
//以下是使用TSL指令实现互斥的算法逻辑
while (TestAndSet (&lock)) { //上锁并检查
//临界区代码段...
lock = false; //解锁
//剩余区代码段...
}
//Swap指令的作用是交换两个变量的值
Swap(bool *a,bool *b) {
bool temp = *a;
*a = *b;
*b = temp;
}
//以下是用Swap指令实现互斥的算法逻辑
//lock表示当前临界区是否被加锁
bool old = true;
while (old == true)
Swap(&lock,&old);
//临界代码段...
lock = false;
//剩余代码段...