请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

理解不了自旋锁

对自旋锁的介绍完全听不懂
请问老师,自旋锁的线程会反复检查锁变量是否可用,然后呢?可用怎么样,不可用又怎么样?
直接就不会让出CPU了,就忙等待了,有点蒙。

当然我猜,这是一种线程的锁定,直到这个线程不用这个资源了,才会彻底解锁,让出线程。但是希望得到严谨的解答,谢谢

正在回答

3回答

这个问题要从自旋锁的实现去回答。

自旋锁在不同语言都有不同的实现,但核心逻辑都是一样的,你可以看做是一个死循环去判断锁变量是否可用,如果可用则跳出循环,否则继续死循环。

逻辑如下:

void spin_lock(lock)
{
    while (test_and_set(lock, true));// 锁可用则返回,否则继续循环
}

需要注意的是,死循环是占用100%的CPU的,也即是不会让出CPU。

有一个跟死循环相关的程序员段子可以分享一下:

程序员小明和女朋友在机场候机,女生突然肚子疼了,小明在心疼之余掏出笔记本写了个四线程死循环提高CPU温度给女生暖肚子,女生非常感动,然后给自己买了一个暖宝宝。

希望对你有所帮助。

0 回复 有任何疑惑可以回复我~
  • 提问者 激发态电子 #1
    还是没太懂
    课程中,生产者每次加一前后都会加锁和解锁,那解锁后,锁变量可用,消费者线程就有机会进行减一操作了。那不就是和互斥锁一样了吗?
    但实际结果不一样,自旋锁效率高很多,我猜测是生产者线程执行完成,才执行的消费者,只进行了一次线程切换。
    回复 有任何疑惑可以回复我~ 2019-08-20 21:11:34
  • 咚咚呛 回复 提问者 激发态电子 #2
    回复消息不能格式化列出来,我贴到问题回复上。
    回复 有任何疑惑可以回复我~ 2019-08-20 21:29:13
  • 1. 加锁解锁的操作是和互斥锁一样的,但是这和锁的实现不冲突。
    2. 加锁和解锁是为了使得别的线程不能进入临界区域,一个线程加锁了,另外一个线程就不能再对其加锁,只能等锁的释放。
    3. 自旋锁会死循环等待,互斥锁会让出CPU。
    4. 至于互斥锁性能比自旋锁性能差的原因,和同学的理解一样,是由于线程切换带来的开销导致的。但是不能片面的认为自旋锁效率一定会比互斥锁高,在一些复杂场景下,互斥锁具有更高的效率。
    回复 有任何疑惑可以回复我~ 2019-08-20 21:32:52
提问者 激发态电子 2019-08-20 21:44:27

多谢老师的解答,老师您列举的这几点,我是可以理解的。

主要纠结的点在于下图:

不明白生产者是怎样一直占有资源直到自己的num+1所有循环完成的。

消费者应该有机会抢到资源的使用权的,这样就和互斥锁没区别啦

https://img1.sycdn.imooc.com//szimg/5d5bf8a109a53a4107430497.jpg

0 回复 有任何疑惑可以回复我~
  • 你是指你执行的结果是num+=1的循环执行完成了,才执行消费num-=1的操作吗?
    回复 有任何疑惑可以回复我~ 2019-08-20 21:54:04
  • 是的,你贴的图的描述没有问题,理论上只要生产者解锁了,消费者就可以获得锁,并拿到资源使用权。这点确实是和互斥锁一致的,只不过spin_lock是会一直占用CPU(死循环检查锁是否可用),直到锁可用,不像互斥锁会让出CPU给操作系统进行别的调度。
    回复 有任何疑惑可以回复我~ 2019-08-20 21:56:53
  • 提问者 激发态电子 回复 咚咚呛 #3
    num + 1执行完,有一个解锁操作,这时候消费者正在自旋等待锁,所以有机会抢到资源,就造成了线程切换,和互斥锁就一样了
    回复 有任何疑惑可以回复我~ 2019-08-20 21:57:06
咚咚呛 2019-08-20 21:33:29

1. 加锁解锁的操作是和互斥锁一样的,但是这和锁的实现不冲突。

2. 加锁和解锁是为了使得别的线程不能进入临界区域,一个线程加锁了,另外一个线程就不能再对其加锁,只能等锁的释放。

3. 自旋锁会死循环等待,互斥锁会让出CPU。

4. 至于互斥锁性能比自旋锁性能差的原因,和同学的理解一样,是由于线程切换带来的开销导致的。但是不能片面的认为自旋锁效率一定会比互斥锁高,在一些复杂场景下,互斥锁具有更高的效率。


0 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信