synchronized

synchronized

synchronized底层是如何实现的 以及 什么是锁的升级和降级?

synchronized是java内建的一种同步机制,当一个线程已经获取到锁了,其他的线程试图获取锁的时候就只能等待或者阻塞在那里。synchronized可以用来修饰方法也可以用来修饰代码块。

synchronized底层是基于一对monitorenter/monitorexit指令来实现的,我们可以通过反编译.class文件看到这两条指令。

在虚拟机中,java对象在内存中存储在堆中,堆中的对象可以分为3个区域:对象头、实例数据、对齐填充数据。

image

java对象头中的mark word区域就有锁状态的标记信息。

所谓的锁升级和降级,就是jvm对synchronized运行的机制,当jvm监测到不同的竞争状况时,会自动切换到不同的锁实现。这种切换就是锁的升级和降级。

在jdk1.6之前,synchronized是重量级锁,运行在虚拟机上,而虚拟机是应用级别的程序,运行在用户态,需要通过操作系统内核程序发申请,得到反馈获得锁,所以称synchronized为重量级锁。就是Monitor的实现完全是依靠操作系统内部的互斥锁,因为需要进行用户态和内核态的切换。

在jdk1.5升级为jdk1.6的过程中,高并发是一个重要的改进项,jdk1.6的版本上开发团队也是花费了大力气为重量级锁减重,实现各种锁优化技术。为了减少获得锁和释放锁带来的性能损耗,提高性能,引入新的概念,无锁、轻量级锁、偏向锁。

锁的状态有四种:无锁、偏向锁、轻量级锁、重量级锁。

伴随着锁的竞争,锁可以从偏向锁升级到轻量级锁再升级到重量级锁。jdk1.6中默认是开启偏向锁和轻量级锁的,我们也可以通过-XX:UseBiasedLocking来禁用偏向锁。

偏向锁就是把当前的锁偏向于某个线程,这种锁适合同一个线程多次去申请同一份资源的时候,并且没有其他线程来和自己竞争的情况下。轻量级锁也可以称为自旋锁,通过多次自旋尝试来获取锁,自旋这种机制能够保证用户态到内核态切换的过程中带来的性能锁损耗。

当有线程来竞争锁资源的时候,synchronized会首先尝试使用偏向锁来处理,如果能够竞争到偏向锁,表示加锁成功,直接返回就好了,如果竞争偏向锁失败,表示当前已经有线程占有了偏向锁,这个时候就会升级到轻量级锁,竞争锁的线程会根据自适应自旋次数去尝试占有锁资源,如果还是没有竞争到锁的话就会升级到重量级锁,在这种状态下没有竞争到锁的线程就会被阻塞,一直等到占有锁的线程执行完任务之后释放锁资源的时候,它才能被唤醒执行任务。这种思想是一种性能和安全性的平衡。

posted on 2024-09-08 14:56  ~码铃薯~  阅读(7)  评论(0编辑  收藏  举报

导航