synchronized原理&JUC原理

92 阅读2分钟

synchronized同步原理 synchronized同步依赖于jvm实现。JUC包依赖于CPU硬件特殊指令实现。 synchronized可作用于实例方法(实例对象),静态方法(Class实例),实例对象(实例对象)。作用粒度为对象。

1)同步对象

1.每个对象都是一个monitor锁,当monitor被占用时就处于锁定状态。执行monitorenter可获得锁的所有权。线程进入monitor时,执行进入数+1,该线程成为monitor的所有者。 2.当进入数为0时,线程可进入monitor,大于0时,线程进入阻塞状态,等待monitor被释放。 3.当线程已占用monitor时,直接重新进入monitor,执行进入数+1(子类同步方法进入父类同步方法时,需重入,否则会被死锁)。

备注:wait方法和notify方法也依赖于monitor。在同步代码块外执行会抛出java.lang.IllegalMonitorStateException的异常。

2)同步方法

为方法增加ACC_SYNCHRONIZED标记。调用方法时检查该标记是否被设置,如有,则线程先获取monitor,获取成功后执行该方法,方法执行完释放monitor。

备注:方法的同步为隐式调用

锁的状态

无锁,偏向锁(单线程情况),轻量锁(并发情况),重量锁

自旋锁

什么是自旋? 在线程进入锁时,发现锁被占用,不再直接挂起,而是开始循环检测锁是否被释放。减少线程的阻塞和释放操作,提高性能。 自旋锁适用于锁的临界区很小的情况。因为自旋锁也占用了CPU的处理时间,而且锁长时间被占用时,自旋只能白白消耗性能。所以自旋必须有一个限度,超过这个限度则停止自旋。因此,JVM提供自适应自旋锁,动态设置自旋锁的限度。当上次自旋成功,则提高限度,允许他等待更长时间。若一直自旋失败,则降低自旋限度,甚至省略掉自旋操作。

锁消除

依据JVM逃逸分析的数据支持(对象的生命周期。当对象被指向静态成员变量或者对象被传入不确定代码中执行时,则发生逃逸)。JVM检测到数据不可能存在竞争,则对同步进行锁消除。

锁粗化

当多个连续加锁,解锁操作连接在一起时,则合并为一个锁。

偏向锁

将monitor偏向当前线程,减少线程加锁解锁操作。hotspot会为对象自动加偏向锁,线程产生竞争则解除偏向锁。

轻量锁

使用自旋

重量锁

不使用自旋