如何理解Java中眼花缭乱的各种并发锁?( 三 )


7)最后,就是锁再设计和锁优化的一些情况先来看分段锁,它是一种锁的再次设计,并不是具体的一种锁 。分段锁设计目的是将锁的粒度进一步细化,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作 。

如何理解Java中眼花缭乱的各种并发锁?

文章插图
在 Java 语言中 CurrentHashMap 底层使用分段锁Segment , 来支持多线程并发操作 。另外,就是锁优化,包括锁消除、锁粗化 。锁粗化就是将多个同步块的数量减少 , 并将单个同步块的作用范围扩大,本质上就是将多次上锁、解锁的请求合并为一次同步请求 。举个例子 , 一个循环体中有一个代码同步块,每次循环都会执行加锁解锁操作 。如代码所示:
private static final Object LOCK = new Object();for(int i = 0;i < 100; i++) {synchronized(LOCK){// do some magic things}}经过锁粗化后,就变成下面这个样子:
synchronized(LOCK){for(int i = 0;i < 100; i++) {// do some magic things} }锁消除是指虚拟机编译器在运行时检测到了共享数据没有竞争的锁,从而将这些锁进行消除 。举个例子让大家更好理解,来看这样一段代码:
public String test(String s1, String s2){StringBuffer stringBuffer = new StringBuffer();stringBuffer.append(s1);stringBuffer.append(s2);return stringBuffer.toString();}上面代码中的test() 方法,主要作用是将字符串 s1 和字符串 s2 串联起来 。test() 方法中的三个变量s1, s2,和StringBuffer都是局部变量,局部变量是存储在栈上的,而栈又是线程私有的,所以就算有多个线程访问 test() 方法也是线程安全的 。我们都知道 StringBuffer 是线程安全的类,因为append()方法是同步方法,如源码所示:
// append 是同步方法 public synchronized StringBuffer append(String str) {toStringCache = null;super.append(str);return this;}但是 test() 方法本来就是线程安全的,为了提升效率,虚拟机自动帮我们消除了这些同步锁,这个过程就被称为锁消除 。
3、总结好了,前面讲了这么多 , 相信大家已经理解了各种眼花缭乱的锁 。最后,我用一张脑图完整地总结了各种锁的应用场景 。大家可以在面试前拿出来看看,只要是被问到锁相关的问题 , 相信你一定能够吊打面试官了 。
如何理解Java中眼花缭乱的各种并发锁?

文章插图
脑图分享链接:https://www.processon.com/view/link/633412ea07912955b20d7938最后,分享几个关于锁的高频面试题,看看大家能不能回答出来
1、ReentrantLock与synchronized 的区别2、synchronized和volatile的区别3、synchronized和lock的区别4、什么是死锁以及如何避免死锁问题如果你回答不出来,可以去我的主页看看,这些面试题在往期的视频中都有分享过 。
我是被编程耽误的文艺Tom , 如果我的分享对你有帮助,请动动手指一键三连分享给更多的人 。关注我,面试不再难!

推荐阅读