学习的秘诀在于——永不止步!!!
来看一则小故事(纯属虚构)
某大厂大牛:你了解synchronized 吗?
某代码小白:嗯!懂一点点
某大厂大牛:那你了解synchronized 锁升级吗?
某代码小白:啥?synchronized 还有这操作?大佬和我说说呗
某大厂大牛:讲锁升级之前,先声明下:synchronized 锁定的并非代码而是一个对象,获取到这个锁定对象才能执行目标代码。再者,锁升级也并非什么高不可攀的东西,简单的讲就是jdk为了提升synchronized 性能所做的优化。
某代码小白:优化?
某大厂大牛:是的优化! 在之前的版本synchronized 由于是重量级锁的缘故导致性能非常低下,但是自从jdk5引进锁升级的概念后性能得到了质的飞跃。
某代码小白:怎么说?
某大厂大牛:通常在锁竞争不强烈的情况下,synchronized 有一个偏向锁的概念,会对第一个线程进行标记,记录下第一个线程的id,再次碰到该线程会直接放行。如果锁的竞争强烈则会升级为轻量级锁通常也被称为自旋锁,对于没有获取到锁资源的线程会有一个等待操作,这个时候线程并不是进入CPU唤醒池等待,而是一直占用着CPU资源。如果锁的竞争进一步加强,那么锁会进一步升级为重量级锁,这个时候锁进入到内核态,归CPU管理
偏向锁:
张三想去洗手间,发现他是第一个,于是他直接推门进入,但是为了防止他人闯入于是他上了锁并且标记张三在用请勿闯入,于是其他人看到这个标记都被拒之门外(因为标记不符),但是张三却可以重复的出入知道标记清除
某代码小白:那么偏向锁是锁吗?
某大厂大牛: 偏向锁并不是锁,只是一种标识,是由对象头中的Mark Word中的2位指定,通常是01表示
某代码小白:哦!懂了,那么自旋锁呢??
某大厂大牛:自旋锁是在锁轻度竞争情况下由偏向锁升级,因为线程存在竞争,为了保证线程同步,会升级成为自旋锁,这个时候线程需要抢夺锁资源,没有抢到锁的线程处于一个活等待(即在等待锁释放但是有没有进入到唤醒池等待),这个时候的线程一直占用着CPU资源。
自旋锁
一群人想去上厕所,但是位置只有一个,于是A抢夺到了锁资源,其他人不想放弃于是就在门口等待,这个时候只要A释放锁(开门出来)那么下一个人就立马夺门而入
某大厂大牛:自旋锁也给你讲了顺便给你讲讲重量级锁。
重量级锁
在自旋锁的基础上,如果锁竞争非常激烈,这个时候发现如果有1000个线程,如果他们都是自旋状态那么就会出现一种情况,大量的占用CPU,最后导致性能电脑非常的卡慢。这个时候就需要将锁升级为重量级锁,将没有获取到锁资源的线程丢入到CPU唤醒池等待唤醒,释放了CPU,类似于排队叫号。
锁升级
某代码小白:哎,那么我们在日常使用中如何选择轻量级锁还是重量级锁?
某大厂大牛:从上面的概念中我们已经了解了两者之间的区别以及特性。
- 轻量级锁处理线程少,处理时间短;
- 重量级锁:线程多,处理时间长
某代码小白:懂了!还有个问题,自旋锁什么时候会升级重量级锁?
某大厂大牛:自旋锁在默认情况下,如果自旋超过10次就会自动升级为重量级锁的。
某代码小白:了解,感谢大佬,大佬牛逼!
某大厂大牛:学习是没有捷径的,只有不断的学习你会发现你学的越多,你会发现我们学习的东西只是冰山一角。
另外注意点:
- 锁的对象不能使用基础变量integer long等以及一些string常量
- 如果程序中产生异常,锁将被释放