为了账号安全,请及时绑定邮箱和手机立即绑定

如下程序,是关于TestAndSet()解决硬体同步的原理的问题

如下程序,是关于TestAndSet()解决硬体同步的原理的问题

PHP
小怪兽爱吃肉 2023-03-02 17:13:42
booleanTestAndSet (boolean *target){boolean rv = *target;*target = TRUE;return rv;}do{while(TestAndSet(&lock))criticalsection;lock= FALSE;remaindersection;}while (TRUE);
查看完整描述

2 回答

?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

这个函数还是十分精妙的!但是有点儿绕

首先纠正一下你代码的错误,while(TestAndSet(&lock))之后是有个分号的,即

while(TestAndSet(&lock));

是个空语句,表示一直在这里死循环。而不是一个劲儿的运行criticalsection。下面说这个机制的原理。

一个线程运行到while(TestAndSet(&lock))这句的时候,

  1. 如果criticalsection没有被锁住,即lock值为false,那么传入TestAndSet()的参数为false,【【在函数体内:rv先被赋为false,然后*target被赋为true,然后返回rv(值为false)。运行的结果为:返回值为false,使线程跳出while循环,得以进入criticalsection;同时参数(即lock)被改为true,表示criticalsection被锁住】】,其他线程在当前线程没有出criticalsection之前(即运行lock=false这句之前),不能进入criticalsection。为什么呢,下面说

  2. 如果线程运行到while(TestAndSet(&lock))时,criticalsection被锁住了,即lock值为true,那么证明有其他线程在运行criticalsection的代码(如第一步所说),那么传入TestAndSet()函数的值为true,《《在函数体内:*target为传入的值(true),rv被赋为true,*target被赋值为true(原来就是true,赋值不改变什么),返回rv。那么运行结果是返回值是rv(true),lock也是true。因为返回值是true,所以while继续运行,lock还是true》》,所以传入TestAndSet()的参数依然是true。在上一句《《》》之间的过程又重新运行一遍,然后一遍又一遍。所以这个线程一直在while这里一直运行,不能进入criticalsection。

    直到在criticalsection中的那个线程运行完criticalsection中的代码,即运行到lock=false这句,lock被赋为false。这时比较关键了,while中再次运行TestAndSet()的时候传入的参数变成了false,那么第一段中【【】】中的过程会运行一遍,即返回值为false,在while中运行了无数次的进程可以跳出while,进入criticalsection,lock又重新被赋为true,即锁住criticalsection,其他进程此时不能进入。

所以“这条语句”的作用就是:如果当前criticalsection被锁定,那么在这里等,直到解锁;如果没有被锁定,当前进程可以进入criticalsection,同时锁定criticalsection。

上面就是原理了,下面说硬同步。

之所以叫硬同步,是因为TestAndSet()函数中的三条语句是由硬件保证同步的,即硬件保证这三条语句必须原子运行,中间不发生任何中断,如同一条语句。之所以这样保证,是因为函数体内本身就是一个criticalsection,在多线程程序中,如果在这几条语句中间被中断,也会有race condition发生。


查看完整回答
反对 回复 2023-03-06
?
动漫人物

TA贡献1815条经验 获得超10个赞

TestAndSet
  一个执行单元要想访问被自旋锁保护的共享资源,必须先得到锁,在访问完共享资源后,必须释放锁。如果在获取自旋锁时,没有任何执行单元保持该锁,那么将立即得到锁;如果在获取自旋锁时锁已经有保持者,那么获取锁操作将自旋在那里,直到该自旋锁的保持者释放了锁。由此可以看出,自旋锁是一种比较低级的保护数据结构或代码片段的原始方式,这种锁可能存在两个问题:

  死锁。试图递归地获得自旋锁必然会引起死锁:递归程序的持有实例在第二个实例循环,以试图获得相同自旋锁时,不会释放此自旋锁。在递归程序中使用自旋锁应遵守下列策略:递归程序决不能在持有自旋锁时调用它自己,也决不能在递归调用时试图获得相同的自旋锁。此外如果一个进程已经将资源锁定,那么,即使其它申请这个资源的进程不停地疯狂“自旋”,也无法获得资源,从而进入死循环。
  过多占用cpu资源。如果不加限制,由于申请者一直在循环等待,因此自旋锁在锁定的时候,如果不成功,不会睡眠,会持续的尝试,单cpu的时候自旋锁会让其它process动不了. 因此,一般自旋锁实现会有一个参数限定最多持续尝试次数. 超出后, 自旋锁放弃当前time slice. 等下一次机会。

 


查看完整回答
反对 回复 2023-03-06
  • 2 回答
  • 0 关注
  • 101 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信