给网站做插画分辨率,网站开发报告参考文献,北京的网站制作,网站建设怎么做?文章目录 1、偏向锁出现的背景2、从共享对象的内存结构看偏向锁3、偏向锁的持有4、启动偏向锁5、sleep暂停来启动偏向锁6、偏向锁的撤销7、总体流程8、SinceJava15 偏向锁的废除 1、偏向锁出现的背景
如果一个线程连续几次抢到锁#xff0c;仍然重复加锁解锁#xff0c;就会… 文章目录 1、偏向锁出现的背景2、从共享对象的内存结构看偏向锁3、偏向锁的持有4、启动偏向锁5、sleep暂停来启动偏向锁6、偏向锁的撤销7、总体流程8、SinceJava15 偏向锁的废除 1、偏向锁出现的背景
如果一个线程连续几次抢到锁仍然重复加锁解锁就会导致用户态和内核态频繁切换这显然是有改进空间的。如之前买票的例子
public class SaleTick {public static void main(String[] args) {Ticket ticket new Ticket();new Thread(() - {for (int i 0; i 50; i) {ticket.sale();}},t1).start();new Thread(() - {for (int i 0; i 50; i) {ticket.sale();}},t2).start();new Thread(() - {for (int i 0; i 50; i) {ticket.sale();}},t3).start();}
}//资源类
class Ticket {private int number 50;Object lockObject new Object();public void sale() {synchronized (lockObject) {if (number 0) {System.out.println(Thread.currentThread().getName() 卖出票剩余票数 number--);}}}
}
发现一个线程一直在抢到锁 Hotspot 的作者发现大多数情况下多线程的情况下锁不仅不存在多线程竞争还存在锁由同一个线程多次获得的情况偏向锁就是在这种情况下出现的它的出现是为了解决只有在一个线程执行同步代码块时提高性能。 偏向锁会偏向于第一个访问锁的线程如果在接下来的运行过程中该锁没有被其他的线程访问则持有偏向锁的线程将永远不需要触发同步。也即偏向锁在资源没有竞争情况下消除了同步语句懒的连CAS操作都不做了直接提高程序性能。
举个例子生活中第一次去店铺A吃牛肉汤老板会问你的口味然后接下来几天天天都去吃这家店那老板以后看到来的是你就不会再问了直接给你按口味做就是了。
2、从共享对象的内存结构看偏向锁
从对象结构来看偏向锁时被锁对象请求头Mark word的前54位都存当前线程的指针末尾的三位则改成了101即代表偏向锁。 3、偏向锁的持有
当线程A第一次竞争到对象锁时修改共享对象Mark Word里的偏向线程ID在没有其他线程竞争的情况下后续这个线程再进入这个同步代码块时不需要再次加锁解锁只需判断对象Mark Word里的ID是不是指向自己
是就直接执行且直到有其他线程过来发生竞争才释放锁不是说明发生了竞争就尝试通过CAS修改Mark Word里的线程ID为自身ID
上面CAS时
如果修改成功说明线程B来改时之前偏向的线程A刚结束此时仍为偏向锁偏向B如果修改失败升级轻量锁保证所有线程重新公平竞争 注意点偏向锁只有遇到其他线程尝试竞争偏向锁时持有偏向锁的线程才会释放锁线程是不会主动释放偏向锁的 偏向锁的操作不会直接捅到操作系统不涉及用户到内核来回转换。以自定义的Account对象的对象头为例 此时线程A执行到synchronized同步代码块时JVM通过CAS操作把线程指针ID记录到Account对象的Mark word 中并修改偏向标识线程A获得锁成功。注意执行完同步代码块后锁并未释放等线程A二次来时JVM判断account的Mark Word里面是否还有线程A的ID有就继续执行因为之前没有释放锁这里自然不用重新获取锁也就不涉及用户态和内核态的来回切换。 4、启动偏向锁
终端执行以下查看偏向锁的配置信息
java -XX:PrintFlagsInitial | grep BiasedLock*可以看到偏向锁默认打开以及启动偏向锁的延迟时长默认延迟4秒我这里JDK版本较高不是4 写实例Demo 可以看到只有一个线程在操作对象o ⇒ 应该是偏向锁 ⇒ 却发现是轻量锁000 这是因为偏向锁延时4秒开启期间自然是下一级轻量锁。 偏向锁在JDK1.6之后就默认开启但启动时间有延迟想立刻启动可通过添加JVM参数将延迟改为0 -XX:UseBiasedLocking 开启偏向锁-XX:-UseBiasedLocking 关闭偏向锁此时会直接跳入轻量锁-XX:BiasedLockingStartupDelay0 关闭延迟
添加JVM参数这里关闭延时正常显示101即偏向锁 5、sleep暂停来启动偏向锁
除了以上添加JVM参数关闭延时来立刻启动偏向锁也可通过另一种方式程序执行前等4秒以保证开启了偏向锁 再对比下偏向锁开启后使用synchronized锁时的对象o和不使用synchronized时的对象o的区别 可以看到二者锁状态均为101但前面o对象未使用synchronized锁所以线程ID为空而后者则带了线程ID。
6、偏向锁的撤销
共享对象o的Mark Word一直指向线程A的ID线程A也一直拿着这个对象锁。直到第二个线程开始来抢夺锁时线程A的好日子结束 偏向锁使用一种等到竞争出现才释放锁的机制只有当其他线程竞争锁时持有偏向锁的原来线程才会被撤销。 且撤销需要等待全局安全点(该时间点上没有字节码正在执行)同时检查持有偏向锁的线程是否还在执行客人还在你店里吃饭你总不能一到打烊时机就掀桌子 如果第一个线程正在执行synchronized方法(处于同步块)它还没有执行完其它线程来抢夺该偏向锁会被取消掉并出现锁升级升级为轻量锁且此时轻量级锁由原持有偏向锁的线程持有继续执行其同步代码而正在竞争的线程会进入自旋等待获得该轻量级锁 第一个线程执行刚好完成synchronized方法(退出同步块)则将对象头设置成无锁状态并撤销偏向锁重新偏向。直白说就是另一线程t2来竞争时偏向的线程t1刚好执行完那大家就重新竞争。当然也有可能t1出代码块后run方法结束直接走了那就偏向t2就行
7、总体流程 8、SinceJava15 偏向锁的废除
JDK15:Disable and Deprecate Biased Locking.
//2020.9.15Prior to JDK 15, biased locking is always enabled and available. With this JEP, biased locking will no longer be enabled when HotSpot is started unless -XX:UseBiasedLocking is set on the command line.