上次我们学习到在进程中的线程对于数据是共享的,那在一个线程对数据进行操作的时候,很有可能遇到中断,将那个线程正在处理的数据进行修改,而中断事件之后,原来的线程还是以为用到的数据就是正确的,这就造成了错误。这里给出临界区的定义————对共享内存进行访问的程序片段。
为了避免这种情况,我们需要保证在一个线程对临界区进行操作的时候,其他线程不会进入临界区,这就是互斥问题。
最简单的方法就是在进入临界区的时候关闭中断然后出临界区的时候再打开。这样的话,如果一个程序在临界区内执行出错了,阻塞了,那么系统将会一直阻塞在临界区内。而且对于多核CPU,关闭中断中对执行本指令的CPU有效,其他CPU还是可以继续运行。
第二种尝试,设置锁变量。
一个进程在进入临界区的时候,检测lock的值,如果是0,则进程将lock置1,进入临界区,出来临界区的时候再lock置0.这样还是存在一个问题,当进程在检测lock值为0之后,置lock为1之前,系统调用了另外一个进程,那个进程将lock置为了1,当第一个进程再次运行的时候,这样就存在两个进程处于临界区。
第三种尝试:peterson方法
假设连个进程同时调用进入临界区的函数,则intersect[0]和interest[1]都等于TRUE,他们都将自己的进程号存入turn,但是只有一个是有效的,因为后存入的将会覆盖之前的turn,这样就保证了进程0进入临界区而进程1将不停的循环。
缺点:这些算法都是在进入临界区的时候进行判断,如果不满足就一直等待,直到许可为止,这样就造成了CPU时间的浪费。更加严重的是有两个进程H,L,其中H的优先级更高,假如L在临界区的时候,此时H变到就绪态准备运行,但是L在临街区内, H就进行忙等待,但是H就绪的时候L无法被调度,H就将一直等待下去,这种就叫做优先级反转。