synchronized 的实现原理以及锁优化?

题目来源:https://zhuanlan.zhihu.com/p/86536581
java面试清单
**java基础 **
synchronized 的实现原理以及锁优化?
线程不安全问题的诱因
1 共享变量的存在
2 多线程共同操作共享数据。
当多线程共同操作共享数据时,希望保证在某一条线程进行操作的时刻,其他同样希望多这个变量进行操作的线程处于等待状态,只有当正在执行的线程操作完成,下一个线程才能继续操作。这个状态就叫做“互斥锁”
3 我们通过添加synchronized这个关键字来实现这样的效果,使用这个关键有一个很好的点是:可以让本条线程的操作而导致的数值变化过程,对其他线程是透明的
synchronized的使用场景
1 修饰实例方法,对实例对象进行加锁
2 修饰静态方法,对类对象进行加锁
3 修饰代码块,对置顶对象进行加锁
synchronized的底层实现原理
jvm中的同步都是有Moniter(管程|监视器锁)对象的控制。
在这里插入图片描述
java中的对象都存放在堆内存中。每一个java对象又有自己的数据结构,重点关注一下对象头这个部分。因为对象头是实现synchronized的锁对象的基础。

java头的内部的数据结构java头的内部的数据结构在这里插入图片描述
在Java头的Mark Word中存储了于锁相关的信息
在这里插入图片描述

synchronized修饰的同步代码块
1 由Mointer对象来完成同步的控制。entermointer表示进入同步代码块;existmointer表示退出同步代码块
2 当执行entermointer时,当前线程将试图去获取对象锁所对应的mointer的持有权。当没有其他线程正在使用时,mointer为0,表示可以对当前线程进行加锁,然后进行后续操作,完成后将mointer重新置位0,表示结束。当mointer不为0时,表示有其他线程正在操作,此时在排队对列中等待。制止其他的锁执行完成
synchronized修饰的同步方法
1 由方法的标志位: ACC_SYNCHRONIZED来隐士实现。
2 当调用方法时,会先检查该方法的这个标志位。如果为1,那么当前线程将持有这个mointer对象,继续操作,执行完毕再释放。

java虚拟机对synchronized这个重量锁的优化
锁的分裂:无锁状态;偏向锁;轻量级锁;重量级锁
升级的方向:从偏向锁一步一步升级到重量级锁,并且这个方向是单向的。
偏向锁:
出现的原因:
在很多时候,锁并不存在多线程竞争的情况,而且往往是由同一个线程多次获得的。
为了减少同一个线程在获取锁的过程中所付出的代价,引入了偏向锁的概念。
核心思想:
如果一个线程获得了锁,那么这个锁就进入了偏向模式。当同一个线程再次请求这个锁的时候,直接获取到这个锁,不用再经过同步的过程。
使用场景:
没有锁竞争的场景。
失败:
直接升级为轻量级锁
轻量级锁
出现原因:
对于绝大部分的锁,在整个同步的周期内都不存在竞争
使用场景:
线程交替执行同步块的场合
失败:
直接升级程重量级锁
自旋锁
出现原因:
当轻量级锁失败晋升为重量级索的过程中,JVM为了避免线程真是的操作系统挂起,使用自旋锁

核心思想:
在大多数情况下,线程持有锁的时间不会太长,如果直接挂起得不偿失,所以使用自旋锁。自旋锁可以让想要获得锁的线程做一个空循环,然后在得到锁
重量级锁synchronized锁
锁消除
JVM在编译的时候会对运行上下文进行扫描,去除不可能存在共享资源竞争的锁。通过这种方式消除没有必要的锁,可以节省毫无意义的请求锁时间。

synchronized锁的可重入性
当其他线程试图操作右当前线程持有的对象锁(即:synchronized锁)所持有的临界资源时,会处于堵塞状态。
但当,当前线程再次请求拥有对象锁(即:synchronized锁)的临界资源时,该请求会成功。这种情况就叫做对象锁的可重入性
线程中断
一 当前线程处于阻塞状态或者试图执行一个阻塞操作时,可以使用实例方法interrupt()进行线程中断,执行中断操作后会抛出interruptException异常(该异常必须捕捉无法向外抛出)并将中断状态复位
二 当线程处于运行状态,我们可以调用实例方法interrupt()进行线程中断,单同时必须手动判断中断状态,并编写中断线程的代码(其实就是结束run()方法体的代码)
中断和synchronized
线程的中断操作对于正在等待获取的锁对象的synchronized方法或者代码块并不起作用。也就是对于synchronized来说,如果一个线程在等待锁,那么结果只有两种,要么它获得这把锁继续执行,要么就保存等待。即使调用中断线程,也不会生效
等待唤醒机制与synchronized
等待唤醒机制主要是指notify/notifyAll/wait方法。在使用这三个方法的时候,这三个方法必须处于synchronized代码块后者synchronized方法中,否则就会抛出异常。因为调用这几个方法必须拿到monitor对象。而synchronized可以活着monitor

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值