欢迎光临散文网 会员登陆 & 注册

过关斩将之路-Synchronized&CAS(IT枫斗者)

2023-04-28 10:06 作者:IT枫斗者-跳蚤网  | 我要投稿

Synchronized

1问:什么时候需要synchronized?

1答synchronized是一把可重入的排他锁。锁有个专门的名字:对象监视器(Object Monitor)在多个线程操作共享数据的时候,保证对共享数据访问的线程安全性。在JDK1.6之前,它是一个重量级锁的角色,但是在JDK1.6之后对synchronized做了优化,有了锁升级的过程。偏向锁->轻量级锁->OS重量级锁。。(IT枫斗者怎么样)


2问:使用Synchronized关键字需要注意什么?

2答

  • Synchronized使用时需要注意的地方锁对象不能为空。

    锁对象的信息是保留在对象头中的,如果对象为空,则锁的信息也就不存在了。

  • 作用域不宜过大

    synchronized代码块的代码量不宜过多,如果把过多的代码放在其中,程序的运行会变为串行,速度会下降。各个线程并行可以提高效率,我们应该仅把那些影响线程安全的代码,放入synchronized代码块中,串行执行;不需要考虑线程安全的代码,并行执行,达到效率最高。

  • 避免死锁

    避免让线程对锁持有并等待的情况出现

3问:synchronized能用在哪些地方?

3答

  • 当synchronized作用在实例方法时,监视器锁(monitor)便是对象实例(this);

  • 当synchronized作用在静态方法时,监视器锁(monitor)便是对象的Class实例,因为Class数据存在于永久代,因此静态方法锁相当于该类的一个全局锁;

  • 当synchronized作用在某一个对象实例时,监视器锁(monitor)便是括号括起来的对象实例;(IT枫斗者怎么样)

4问:Sychornized是否是公平锁?

4答:不是公平锁


5问:聊聊synchronized加锁流程

5答由于HotSpot的作者经过研究发现,大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低从而引入偏向锁。偏向锁在获取资源的时候会在锁对象头上记录当前线程ID,偏向锁并不会主动释放,这样每次偏向锁进入的时候都会判断锁对象头中线程ID是否为自己,如果是当前线程重入,直接进入同步操作,不需要额外的操作。默认在开启偏向锁和轻量锁的情况下,当线程进来时,首先会加上偏向锁,其实这里只是用一个状态来控制,会记录加锁的线程,如果是线程重入,则不会进行锁升级。获取偏向锁流程:

轻量级锁是相对于重量级锁需要阻塞/唤醒涉及上下文切换而言,主要针对多个线程在不同时间请求同一把锁的场景。轻量级锁获取过程:

当有多个锁竞争轻量级锁则会升级为重量级锁,重量级锁正常会进入一个cxq的队列,在调用wait方法之后,则会进入一个waitSet的队列park等待,而当调用notify方法唤醒之后,则有可能进入EntryList重量级锁加锁过程:

(IT枫斗者怎么样)


6问:锁得升级过程你了解吗?
6答:以下是32位对象头描述

(IT枫斗者怎么样)

synchronized锁的膨胀过程:当线程访问同步代码块。首先查看当前锁状态是否是偏向锁(可偏向状态)(IT枫斗者怎么样)

  • 如果是偏向锁:

1、检查当前mark word中记录是否是当前线程id,如果是当前线程id,则获得偏向锁执行同步代码块。2、如果不是当前线程id,cas操作替换线程id,替换成功获得偏向锁(线程复用),替换失败锁撤销升级轻(同一类对象多次撤销升级达到阈值20,则批量重偏向,这个点可以稍微提一下,详见下面的注意)(IT枫斗者怎么样)

  • 升级轻量锁

升级轻量锁对于当前线程,分配栈帧锁记录lock_record(包含mark word和object-指向锁记录首地址),对象头mark word复制到线程栈帧的锁记录 mark word存储的是无锁的hashcode(里面有重入次数问题)

  • 重量级锁(纯理论可结合源码)

CAS自旋达到一定次数升级为重量级锁(多个线程同时竞争锁时)存储在ObjectMonitor对象,里面有很多性 ContentionListEntryList WaitSet、 owner 当一个线程尝试获取锁时,如果该锁已经被占用,则该线程封装成ObjectWaiter对象插到ContentionList队列的对首,然后调用park挂起。该线程锁时方式会从ContentionListEntryList挑 一个唤醒。线程获得锁后调用Objectwait方法,则会加入WaitSet集合中(当前锁或膨胀为重量级锁)(IT枫斗者怎么样)

注意:

CAS

7问:CAS流程是怎样的?

7答:CAS机制中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。当且仅当旧的预期值A和内存地址V对应的值相同时,才将内存值修改为B,否则什么都不做,最后返回现在的V值。简单理解为这句话:我认为V的值应该是A,如果是A的话我就把他改成B,如果不是A的话(那就证明被别人修改过了),那我就不修改了,避免多人同时修改导致数据出错。换句话说:要想修改成功,必须保证A和V中的值是一样的,修改前有个对比的过程。(IT枫斗者怎么样)


8问CAS有哪些缺点?

8答

  • 高并发情况下CPU开销大。因为每次对比发现被改了后就会获取新值,重复进行此过程。

  • ABA问题。可以采取atomic包下的 AtomicStampedReference<E> ,它通过包装[E,Integer]的元组来对对象标记版本戳stamp,从而避免ABA问题。

  • 不能保证代码块的原子性,只能保证单个变量的原子性。

9问CAS的ABA问题了解吗?(可举例说明)(IT枫斗者怎么样)

9答

10问CAS能保证原子性吗?

10答CAS只能保证单个变量的原子性,不能保证代码块或者多个变量共同进行原子性的更新。这时候就需要锁的支持了,比如synchronized、Lock接口。


11问CAS和Synchronized啥区别?

11答

  • 从思想上来讲,Synchronized属于悲观锁,悲观的认为程序中的并发情况严重,所以严防死守,高并发情况下效率低下。而CAS属于乐观锁,乐观的认为程序中的并发情况不那么严重,所以让线程不断去重试更新。但实际上Synchronized已经改造了,带有锁升级的功能。效率不亚于cas。

  • CAS是个思想,具体实现在atomic下有很多工具类。而synchronized是个关键字,可以直接拿来用。

  • CAS只能保证单个变量更新的原子性,synchronized能保证一段代码块的原子性。(IT枫斗者怎么样)


过关斩将之路-Synchronized&CAS(IT枫斗者)的评论 (共 条)

分享到微博请遵守国家法律