进程互斥实现方法

进程互斥

  • 前言
  • 1. 软件实现方法
    • 1.1 单标志法
    • 1.2 双标志先检查法
    • 1.3 双标志后检查法
    • 1.4 peterson算法
  • 2. 硬件实现方法
    • 2.1 关中断法
    • 2.2 TestAndSet
    • 2.3 Swap指令

前言

进程互斥:当一个进程访问某临界资源时,另一个想要访问该临界资源的进程必须等待。当前访问该临界资源的进程访问结束并释放该临界资源后,另一个进程才能进行访问。

do {
	entry_section; // 进入区,检查并上锁
	critical_section; // 临界区
	exit_section; // 退出区,解锁
	remainder_section; // 剩余区
} while (true)

为实现对临界资源的访问,同时保证系统的整体性能,需要遵循以下原则:

  • 空闲让进:当临界区空闲,可以允许一个进程立即进入临界区
  • 忙则等待:当有进程进入临界区,当前想要进入临界区的进程必须等待。
  • 有限等待:一个进程必须在有限的时间内能够进入临界区(防止饥饿)。
  • 让权等待:当一个进程在等待临界区资源时,应该立即释放处理机资源,防止忙等待。

1. 软件实现方法

1.1 单标志法

算法思想:两个进程在访问完临界区之后,会把访问权限赋给另一个进程。也就是说,访问临界区的权限只能由另一个进程赋予。

int turn = 0; // 表示当前运行进入临界区的进程号

// 进程 0
while(turn != 0);
critical_section;
turn = 1;
remainder_section;

// 进程 1
while(turn != 1);
critical_section;
turn = 0;
remainder_section;

问题:当进程1使用完临界区之后,假设进程0一直不适用临界区,那么进程1就始终无法再次进入临界区,违反了“空闲让进”原则。

1.2 双标志先检查法

算法思想:设置一个布尔型数组 flag[],用于表示各个进程进入临界区的意愿。如果flag[0] = true则表示0号进程想要进入临界区。

bool flag[2];
flag[0] = false;
flag[1] = false;

// 进程 0
while(flag[1]); // 如果对方要进入临界区,则等待
flag[0] = true;
critical_section;
flag[0] = false;
remainder_section;

// 进程 1
while(flag[0]); // 如果对方要进入临界区,则等待
flag[1] = true;
critical_section;
flag[1] = false;
remainder_section;

主要问题:检查和上锁的操作无法一气呵成,如果发生进程切换,会违反忙则等待原则。

1.3 双标志后检查法

算法思想:先上锁,后检查,避免出现1.2的问题。

bool flag[2];
flag[0] = false;
flag[1] = false;

// 进程 0
flag[0] = true;
while(flag[1]); // 如果对方要进入临界区,则等待
critical_section;
flag[0] = false;
remainder_section;

// 进程 1
flag[1] = true;
while(flag[0]); // 如果对方要进入临界区,则等待
critical_section;
flag[1] = false;
remainder_section;

主要问题:如果进程上锁后立马发生进程切换,会造成死锁,违背了空闲让进和有限等待原则。

1.4 peterson算法

算法思想:结合单标志法、双标志法的思想,既设置各自使用临界区的意愿,又增加谦让标志。

bool flag[2];
flag[0] = false;
flag[1] = false;
turn = 0; // 表示谦让给进程0使用

// 进程 0
flag[0] = true; // 我想要使用临界区
turn = 1; // 谦让给进程1优先使用
while(flag[1] && turn == 1); // 如果对方要进入临界区,则等待
critical_section;
flag[0] = false;
remainder_section;

// 进程 1
flag[1] = true; // 我想要使用临界区
turn = 0; // 谦让给进程1优先使用
while(flag[0] && turn == 0); // 如果对方要进入临界区,则等待
critical_section;
flag[1] = false;
remainder_section;

主要问题:仍旧未遵循让权等待原则。

2. 硬件实现方法

2.1 关中断法

...
关中断指令; // 关中断之后不允许当前进程被中断,自然不会发生进程切换
critical_section;
开中断指令;
...

优点:简单、高效
缺点:不适用于多处理机环境,关中断指令仅对当前处理机有效;关中断指令为特权指令,只适用于内核程序。

2.2 TestAndSet

又称为TestAndSetLock,简称TS或TSL指令,由硬件实现,不可被中断。

bool lock = true; // 布尔型共享变量,表示临界资源是否被加锁

bool TestAndSet(bool *lock) {
	bool old;
	old = *lock;
	*lock = true;
	return old;
}

// 进程中:
while (TestAndSet(&lock));
critical_section;
lock = false;
remainder_section;

优点:实现简单;适用于多处理机环境。
缺点:不满足让权等待。

2.3 Swap指令

又称Exchange指令,或 XCHG.

// 交换两个变量的值
swap(bool *a, bool *b){
	bool tmp = *a;
	*a = *b;
	*b = tmp;
}

// lock 表示当前临界资源是否被上锁
bool old = true;
while (old)
	swap(&old, &lock);
critical_section;
lock = false;
remainder_section;

优缺点同 TSL。

你可能感兴趣的:(操作系统,计算机基础,linux)