请问这一段代码的加锁原理是啥
加锁的代码同样需要保护。所以必须有一个guard,来保证加锁过程不被打断。
这段代码中,TestAndSet 是CPU提供的原子操作指令。它是各种锁算法的核心。
除了原子操作指令,其它指令都可能在执行过程中出现“执行权切换”。多条指令构成的一段程序就更不用说了。
如果guard被置1,就说明flag正在被其它进程/线程修改,那么当前代码就不能碰flag了;否则,说明flag可以安全修改。
如果先检查guard、然后再置1,那么就可能在检查guard之后、对它置1之前出现控制权切换。这就可能导致两个进程同时拿到锁。所以这里必须用TestAndSet指令——正如前面说过,加锁代码同样需要保护,TestAndSet指令给guard加锁时,也是如此。这个保护由硬件自动完成(也可能是TestAndSet函数内部用内存屏障指令手动锁)。
【请问这一段代码的加锁原理是啥】 换句话说,硬件保护TestAndSet指令执行时guard的安全;guard又保护lock函数执行时,flag的安全;flag最终被程序员用来保护某种共享资源的安全——整个传递链条,任何一环出问题都不行。
■网友
TestAndSet 也是一个原子操作,guard 值如果为 1,就表示别的线程正在执行 lock 操作,比如正在设置 flag 或 enqueue,那么 while 语句就会构成一个 SpinLock,直到其他线程把 guard 重新置 0,这个线程才有机会通过 TestAndSet 将 guard 设为 1,另外原子操作的具体功能和实现可能不一致,在这里应该是设置完返回原始值。
■网友
这个是对spinlock的改造,加入阻塞队列,而不是忙等。如果只有一个flag,那么阻塞的时候如何修改flag呢。必须在阻塞之前释放spin锁,那么释放锁之后再阻塞,队列操作就会被打断,因此需要一个guard。guard就是spinlock,用来保护flag,阻塞队列的,而flag用来指示是否需要挂起。如果没有阻塞队列维护,guard跟flag就可以合并,就是spin锁了。其实实际系统spinlock还要关中断或者禁止当前cpu切换线程。否则cpu A线程1获取spinlock后,发生线程切换,那么其他cpu再来获取spinlock时都会忙等,等到cpu A线程1继续运行才行,这样就太浪费cpu了。spinlock一般用于cpu间同步,获取锁之后应该尽快释放。
■网友
感觉这个spin lock的flag和q在可见性上有BUG呀,难道上层保证了这个每个lock_t都只在一个CPU上运行?
■网友
非计算机科班出身,没深入学过操作系统。不过就这个代码本身来说,guard只是用来保证lock和unlock函数本身的原子性。如果只看lock函数,按你的方法,用flag代替lock确实可以保证两个lock调用的互斥。但是如何保证两个unlock的互斥,或者lock和unlock间的互斥呢?用guard应该是一种简单明了的办法。其实这里可以把lock和unlock换成任何功能的函数,guard都可以用来保证原子性。所学有限,如有差错,还请海涵
推荐阅读
- 怎样对别人的代码进行适当修改使他永远也找不到问题出在哪
- 李嫣|李嫣这是怎么了?深夜更改账号签名,还发出一段伤感视频
- 我有几个app点子,拉出来比较容易实现的一个和大家探讨,只差程序员(替你们说了)请问这个点子咋样
- 作为一个打码的,有没有一段时间特不想打码,后来是咋熬过来的
- 异乡好居说程序员删除代码是未经证实的传言吗
- 这段代码中对 vector 的访问为啥不会越界
- C语言指数函数代码
- 学计算机就是当码农吗
- 姑苏区|姑苏区:建设大运河文化带“最最精华的一段”
- 益智贝贝玩具|哈弗大狗的首批车主,开了一段时间后,总结出这几点
