慕课君

V1

2022/09/06阅读:14主题:极简黑

Java面试重灾区:怎么理解自旋锁?

如何理解自旋锁?

最近总有同学问我:

对自旋锁的介绍完全听不懂 。我猜,这是一种线程的锁定,直到这个线程不用这个资源了,才会彻底解锁,让出线程。但是希望得到严谨的解答,谢谢。

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

自旋锁是用于多线程同步的一种锁,线程反复检查锁变量是否可用。由于线程在这一过程中保持执行,因此是一种忙等待,也即是名字中“自旋”本身的含义。

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

逻辑如下:

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

生产者每次加一前后都会加锁和解锁,那解锁后,锁变量可用,消费者线程就有机会进行减一操作了。那不就是和互斥锁一样了吗?

是的,就锁的使用上,自旋锁的使用方式和互斥锁的使用并无太大区别。

但需要注意的是,自旋锁等待的过程是100%一个核的CPU的,也即是不会让出CPU,这一点和其他锁不同。

既然这种锁会100%占用CPU,那为什么计算机需要有自旋锁这种锁,对计算机的性能有什么好处呢?

这是好问题,为什么计算机内部的实现需要自旋锁,这需要联系前面学习的知识。

通过前面的学习我们知道,进程或者线程在运行的时候,是有上下文的,当不同线程进行切换的时候,为了让线程可以运行起来,需要很多的准备工作,这个准备工作,我们称为“上下文切换”。

在CPU的一个核中,每秒钟可会进行万级~十万级别的上下文切换次数,每次上下文切换都需要一定的成本,因此频繁的上下文切换会对计算机性能造成较大的影响。

锁的好处就是它只是忙等待,线程始终在运行,相比互斥锁的使用,避免了上下文切换。

所以这也限定了互斥锁的使用范围,如果互斥锁等待的时间过长,那么由于它本身对CPU的占用,会导致别的线程无法使用CPU。

因此,互斥锁适用于可预见等待时间很短的多线程同步场景,而对于等待时间不可预测或者等待时间很长的场景,仍然是互斥锁具备更高的效率。


内容来自全栈工程师咚咚呛

目前就职于BAT的大数据部门,超过4年的技术研发经验,熟悉java、python研发,担任过多个系统研发主程。

目前专注于分布式系统研发,在高并发、分布式系统有丰富的经验。著有《从原理到实战掌握超实用底层技术》课程。

- END -

分类:

后端

标签:

Java

作者介绍

慕课君
V1