关于synchronized 关键字锁升级的过程
在jvm1.6之前,加synchronized 关键字,默认都是使用的重量级锁
重量级锁:
在创建锁对象后,并对该对象进行synchronized 修饰进行后,这个对象会关联一个Monitor(管程)对象。
这个monitor对象中包含三个属性Owner,entryList,waitSet
当线程t1获取到这个锁,这个锁关联的Monitor的Owner就会关联上这个t1线程。
这个时候其他线程t2过来尝试获取到这个锁时,会先看Owner是否关联上线程。
现在Owner中已经关联上t1线程,那就表示t2线程没法获取到这个锁,于是这个t2线程就会进入entryList(就绪线程队列)
当t1线程用完cpu,释放锁后,jvm就会到entryList中去选择一个就绪态的线程,在Owner中关联新的线程
线程中获取到锁的线程可以通过wait方法进行对锁的释放,这个释放了锁的线程就会进入waitSet中,当这个线程继续notify后,变成就绪态,再次进入entryList,就能再次继续锁的争抢
由于重量级锁会涉及到线程切换,这样也会消费资源,所以在1.6之后,就会有一个锁升级的过程
偏向锁----->轻量级锁---->重量级锁
偏向锁:
在很多时候争取锁的都是同一个线程,这样如果一开始就是重量锁,让同一个线程不停的切换就会很多余。这个时候采取一个偏向锁的模式,不用关联monitor对象,创建一个锁对象时,默认是一个可偏向锁,比如这样t1线程中创建锁对象,会在锁对象的对象头(mark key)标记t1线程,t1线程释放锁后,锁对象的对象头仍然标识的是t1线程(一个线程反复加锁的时候才会有便利)
轻量锁
当锁对象为可偏向锁,且另一个线程想要获取这个锁时,会自动升级为轻量级锁,进行CAS自旋,自旋过程新线程会不停尝试获取锁对象,这个过程会消耗cpu资源,不会进入就绪等待
重量级锁
轻量级锁虽然节省了线程切换的资源浪费,但是当自旋的线程过多,或者自旋次数过多(当自旋的线程循环超过10次,或者线程等待的数量超过cpu的1/2,),也是一个没有必要的浪费,这个时候就会自动升级为重量级锁

浙公网安备 33010602011771号