进程同步:互斥的访问临界资源
实现方式有软件,硬件的两种方式,这里介绍【软件实现方法】
单标志法
:两个进程,A和B,公用一个变量flag,默认为0,值为0时候,A进程可以访问,访问完解锁,标志改为1,B进程标志为1的时候可以访问,访问完了解锁改为0
问题:这样做的话,必须两个进程交替执行才可以,如果A和B进程都执行完了,B进程还需要再执行一次,这个时候flag已经改了0了,而B进程执行的前提条件是为1的时候才执行,会原地死循环,无法再次执行
双标志先检查
:公共变量升级为数组的形式,维护一个公用的数组flag
例如:flag[false,false],数组的下标索引0和1对应的进程A和B
当两个进程都需要执行的时候,A进程判断flag[1]是否为false,为false代表B进程执行完了,然后进程A执行,执行的时候加锁,flag[0]改为true,标识自己目前在执行,执行完之后解锁,flag[0]改为false,标识执行完了。B进程判断flag[0]是否为false,为false标识A进程执行完了,自己可以执行了,执行的时候改写flag[1]的参数,同A进程道理一样;
问题:数组flag[false,false],会导致A和B进程同时执行,我们要保证只有一个进程访问,但是现在导致两个进程同时操作了,会导致数据错乱
双标志后检查
:还是使用数组来实现,同上,区别如下
例如:flag[false,false],数组的下表0和1代表A进程和B进程自己的变量
当两个进程执行的时候,先检查是会判断下flag[1]和falg[0]的值,然后才进入,那么我们先改下值,在判断,就是后检查,比如A进程执行的时候,将flag[0]改为true,代表自己在执行,然后判断flag[1]是否为false,如果为false,标识B进程没在执行,自己可以跑,执行完了将flag[0]改为false,B进程执行的时候flag[0]改为true,判断flag[1]是否为false,为false的话表示A没有在用,自己可以用,用完了flag[0]改为false;
问题:和先检查的问题一样,并发执行的话,两个变量都改为true了,然后一直死循环,A和B进程都无法正常进入了
搬了一天的砖,接着继续。
皮特森算法
:使用公有数组+变量来进行判断,代码不多,但是逻辑相比较上面的会复杂一点点,贴个图
皮特森算法
:声明共有变量flag[false,false],数组的下标对应进程A和进程B,声明共有变量turn=0;
让权等待,由于一个进程一直自旋,while在那里死循环,所以没有让权等待,一直在占用cpu资源,忙等,一直在死循环所以是忙等
示例1:当两个进程执行的时候,进程A,改写数组flag[0] = true,改写变量true=1,表示了自己当前正在执行,执行到while的时候,如果进程B没在执行,那么这个循环是不成立的,因为flg[1]默认为false,直接跳过循环走后面代码了,进入临界区了
示例2:进程A,改写数组flag[0] = true,改写变量true=1,表示了自己当前正在执行,执行到while的时候,进程B这个时候也执行了,执行到了flag[1]=true,然后进程A接着往下走,,判断flag[1]为true,成立,turn为1,也成立,一直不停的自旋,然后进程B的代码继续往下走,走到了turn为0,这个时候进程A的while条件不成立了,就进入到了后续的流程中,B进程,这个时候flag[1]为true,turn也为0,那么会自己进入自旋中,等A执行完
示例3:B进程先执行的原理同示例1和示例2
问题:皮特森算法,是否会导致两个进程都进入死循环之中,无法解开?
答案:根据示例1和示例2的结论来说,是不会的,可以实现两个进程交替访问,只有一个进程访问临界区,操作相关的数据
现在都用皮特森算法了,不用其他得了,以上内容来自B站【JAVA官网】up主,内容基本都是mashibing教育,我只是用文档的形式写了一遍,非我所创