本文是SynChronized详解的第一部分。主要围绕以下三个问题进行解析。
- synchronized 的作用你了解吗?如何保证原子性、可见性和有序性?
- synchronized 作用于实例方法,静态方法,对象实例的差别是什么?
- synchronized遇到异常会释放锁吗?
备注:如果不方便看文章,可以直接去看我的视频,抖音搜索【程序员一棵树】。
1. synchronized 的作用你了解吗?
提到synchronized,你会想到什么?加锁吗?如果你在面试的时候直接这样回答,虽然没有错,但是可能还不足以给面试官留下深刻的印象。我们可以尝试从并发相关的特性触发去回答这个问题。主要从原子性,可见性,有序性这几个方面去进行分析和回答其作用。
- 原子性:确保线程互斥的访问同步代码;底层通过JVM来实现,同一时间只能有一个线程去执行synchronized 中的代码块(涉及对象头,monitor等,后续文章有讲解)
- 可见性:保证共享变量的修改能够及时可见。sychronized底层是通过monitorenter,monitorexit指令加解锁。我们通过下面一张图来了解下这块JVM层的指令的实现
-
- 补充:volatile底层JVM是通过内存屏障来实现的。
- 有序性:有效解决重排序问题。通过monitorenter、monitorexit指令嵌入内存屏障。下图展示了在jvm层面是如何实现有序性的。
我们这边整理一下前面提到过的内存屏障。主要有如下四条禁止重排序的内存屏障
- StoreStore屏障:禁止StoreStore屏障的前后Store写操作重排
- LoadLoad屏障:禁止LoadLoad屏障的前后Load读操作进行重排
- LoadStore屏障:禁止LoadStore屏障的前面Load读操作跟LoadStore屏障后面的Store写操作重排
- StoreLoad屏障:禁止LoadStore屏障前面的Store写操作跟后面的Load/Store 读写操作重排
2. synchronized 作用于实例方法,静态方法,对象实例的差别你知道吗?
- 当synchronized作用在实例方法时,锁(monitor)的是对象实例(this);示例如下图
- 当synchronized作用在静态方法时,锁的是对象的Class实例,因为Class数据存在于元空间(JDK8前是永久代),因此静态方法锁相当于该类的一个全局锁;示例如下图
- 当synchronized作用在某一个对象实例时,锁的是括号括起来的对象实例(XXX);示例如下图
3. synchronized 遇到异常会释放锁吗?
当synchronized遇到异常会自动释放线程占有的锁,因此不会导致死锁现象发生;注意和Lock类的区别。
最后我们补充一下,synchronized也是可重入锁。
更多内容以及源码,请关注公众号【程序员一棵树】
D音,B站 搜索【程序员一棵树】。