概念
synchronized
是Java中的一个关键字,主要作用是解决多个线程之间访问资源的同步性,它可以保证被其修饰的方法或者代码块在任意时刻只有一个线程执行。
使用
synchronized
关键字的使用方式:
- 修饰实例方法
- 修饰静态方法
- 修饰代码块
1)修饰实例方法
加锁的对象是当前对象实例this,进入同步代码块钱要获取当前实例对象的锁。
synchronized void func() { |
2)修饰静态方法
加锁的对象是当前类的Class对象,作用于所有类实例对象。
原因:因为静态成员不属于实例对象,而是属于类。
synchronized static void func() { |
问题:静态同步方法和普通同步方法之间互斥吗?
答:不互斥,二者加锁的对象不同。
3)修饰代码块
加锁的对象时 括号内指定的对象/类:
synchronized(obj)
:进入同步代码块之前要获取实例对象obj的锁synchronized(类.class)
:进入同步代码块之前要获取类的Class的锁
// 等价于 修饰实例方法 |
synchronized可以修饰构造器吗?
答案:不可以,参考https://www.cnblogs.com/datamining-bio/p/13067776.html
synchronized底层原理
想要了解这部分知识,我们需要从字节码层面去看。
同步语句情况
示例代码:
public class SynchronizedDemo { |
执行:
javac SynchronizedDemo.java |
从执行结果可以看出,synchronized
同步语句块使用的字节码指令是monitorenter
(同步代码块开始位置)和monitorexit
(同步代码块结束位置)。
上述的字节码中包含了一个monitorenter
和两个monitorexit
指令,目的是为了保证锁在同步代码块正常执行和出现异常的情况都可以被正常释放。
执行monitorenter
指令时,线程尝试获取锁,也就是获取
对象监视器monitor
的持有权。
wait/notify
方法也依赖于monitor
对象 => 只有在同步代码块中才能调用这两个方法。
如果此时锁的计数器为0,表示该锁可以被获取,获取后将锁的计数器加一,获取锁成功。如果获取对象锁失败,当前线程需要阻塞等待,直到锁被持有锁的线程释放为止。
只有拥有对象锁的持有权的线程才可以执行monitorexit
指令来释放锁。执行该指令后,锁计数器减一,表示锁释放,当计数器为0时,其他线程可以尝试获取锁。
同步方法情况
示例代码:
public class SynchronizedDemo { |
执行:
javac SynchronizedDemo.java |
从字节码层面可以看出synchronized
修饰的方法没有monitorenter
和monitorexit
指令,在方法上存在了一个标识ACC_SYNCHRONIZED
,该标识表明该方法是一个同步方法,此时JVM底层会执行相应的同步调用,判断如果是实例方法,JVM会尝试获取实例对象的锁;如果是静态方法,JVM会尝试获取当前类的Class对象的锁。
JDK6及以上版本对于synchronized的优化
参考:https://www.cnblogs.com/wuqinglong/p/9945618.html
JDK6对锁的实现引入了像偏向锁、轻量级锁、自旋锁、适应性自旋锁、锁消除、锁粗化等技术来优化锁,减少锁操作的开销。
此版本之后,锁的状态变成了四种:
- 无锁
- 偏向锁
- 轻量级锁
- 重量级锁
从上至下竞争逐渐激烈。锁可以升级不可降级,这种策略是为了提高获得锁和释放锁的效率。
synchronized和volatile的关系
在Java中,这两个关键字是互补的关系。
volatile
关键字是线程同步的轻量级实现,因此volatile
的性能是要优于synchronized
关键字的volatile
作用于变量,synchronized
作用于方法和代码块volatile
能够保证数据的可见性,但是不能保证数据的原子性;synchronized
二者都能保证volatile
主要解决变量在多个线程之间的可见性;synchronized
主要解决多个线程之间访问资源的同步性
参考文章
- https://blog.csdn.net/TZ845195485/article/details/109211725
- https://blog.csdn.net/TZ845195485/article/details/109398066
- https://javaguide.cn/java/concurrent/java-concurrent-questions-02.html
- https://www.cnblogs.com/wuqinglong/p/9945618.html