醋醋百科网

Good Luck To You!

高并发面试题汇总-Synchronized部分面试题(二)

什么是锁的粗化和消除?

锁消除

主要是在编译阶段通过逃逸分析来检测到一些被添加了同步操作的方法,在实际上不会出现了共享数据竞争的问题,从而对锁操作进行了消除的操作。

锁粗化

理论上讲,同步代码块的作用范围越小越好,这样可以保证代码块中的其他内容可以并发方法不影响业务,但是如果在某个操作中一系列的连续操作都需要对同一个对象进行反复的加锁解锁,甚至有些时候加锁操作是在一个循环体中,这种情况下,频繁的加锁解锁反而会造成系统性能上的损耗。在这种情况下就需要增加锁的作用范围来,这种增加锁的作用范围的操作就被称为是锁粗化。

为什么Synchronized是悲观锁?什么是乐观锁?什么是CAS?

很显然Synchronized是一个悲观锁,因为它所执行的并发策略是无论有没有必要,都要对数据进行加锁,并且通过锁计数操作来完成锁定检查是否获取到锁。

随着硬件指令集的发展,我们可以使用基于冲突检测的乐观的并发策略来实现乐观锁。意思就是先对数据进行操作,如果没有其他的线程修改数据,那么就说明操作成功了,如果有其他的线程操作了数据,这就说明数据发生了冲突,这个时候就需要对数据进行补偿。这种方式就被称为是乐观执行,也被称为非阻塞的同步操作。

乐观锁是通过CAS算法来实现,涉及到三个操作数,分别是内存值、预期值、新值。当且仅当预期的值与内存值相同的时候,才会就爱你个内存的值更新为新的值。这样处理的前提就是去检查内存中的值是否与原始值是一样的,如果不一样就说明该数据被修改了,这个时候就需要放弃本次的修改操作,否则就说明在操作过程中没有其他线程对值进行修改,这样就将新的值赋值到内存中。

由于这种操作可能会出现ABA问题,所以一般情况下,我们在操作CAS算法的时候还会添加一个版本号来进行ABA问题的规避。

CAS操作是具有原子性的,它的原子性操作是通过CPU的硬件指令操作来进行保证,也就是JDK中提到的Unsafe类。

乐观锁一定最好么?

根据上面的介绍,乐观锁避免了像是悲观锁产生的那种线程独占的问题,在一定程度上提高的并发的性能,但是它也是有缺点的。

  • 乐观锁只能保证一个共享变量的原子性操作,如果在某个执行操作中对于多个共享变量要保证其线程安全,显然乐观锁就有点力不从心了,因为操作逻辑比较麻烦,但是通过互斥锁机制就可以轻松解决。
  • 乐观锁可能会因为自旋操作而影响性能。
  • ABA问题,什么是ABA问题呢?CAS操作的核心就是比较交换,在上面我们提到了其判断的基准,就是原来获取到的内存值,与现在获取到的内存值相同的时候,就说明内存中的数据没有被修改,这种情况下,可以直接将内存值改成新的值。那么如果存在线程A将内存值从1变成2,在线程B还未执行到的时候,又将2改成了1,这个时候线程B进行判断的时候,就还是1,这个时候,就出现了ABA问题,为了解决这个问题,就引入了数据版机制。每次变化版本号都会增加。
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言