多线程一撸到底

偏向锁、自循锁、轻量级锁、重量级锁

偏向锁:“偏向”的意思是,偏向锁假定将来只有第一个申请锁的线程会使用锁(不会有任何线程再来申请锁),因此,只需要在Mark Word中CAS记录owner(本质上也是更新,但初始值为空),如果记录成功,则偏向锁获取成功,记录锁状态为偏向锁,以后当前线程等于owner就可以零成本的直接获得锁;否则,说明有其他线程竞争,膨胀为轻量级锁。

轻量级锁:轻量级锁是相对于重量级锁而言的。使用轻量级锁时,不需要申请互斥量,仅仅将Mark Word中的部分字节CAS更新指向线程栈中的Lock Record,如果更新成功,则轻量级锁获取成功,记录锁状态为轻量级锁;否则,说明已经有线程获得了轻量级锁,目前发生了锁竞争(不适合继续使用轻量级锁),接下来膨胀为重量级锁。

重量级锁:内置锁在Java中被抽象为监视器锁(monitor)。在JDK 1.6之前,监视器锁可以认为直接对应底层操作系统中的互斥量(mutex)。这种同步方式的成本非常高,包括系统调用引起的内核态与用户态切换、线程阻塞造成的线程切换等。因此,后来称这种锁为“重量级锁”。

此处引用自 https://www.jianshu.com/p/36eedeb3f912

volatile、synchronized

volatile:被volatile修改的对象在多个线程之间共享时,每个线程都会强制同步数据,保证每个线程读取的是同一个值,但是并不能解决并发的问题,只能保证对象的可见性

synchronized:可以修改代码块,方法,静态方法。修饰代码块时需要一个锁对象,修饰方法和静态方法不需要。但是在修饰方法时,锁的是当前类的实例对象;修饰方法块的时候需要一个锁对象参数;修饰静态方法锁的是当前类对象,所有调用这个方法的地方都是共享一个所对象

乐观锁、悲观锁

乐观锁:认为所有线程都没有竞争同一个资源,所有的线程都是顺序执行,不存在并发竞争
悲观锁:认为所有线程都存在竞争同一个资源,对这个资源所有的线程执行都需要加锁处理。

乐观锁的场景应用有数据库乐观锁,CAS。数据库乐观锁实现一般是有一个version字段记录当前版本,每次更新时都根据version的值来做操作,数据库中的操作都是顺序执行的,所以前一个操作成功了,后一个version不更新就会操作失败。CAS是CPU的指令级操作,是一个原子操作,在UNSAFE类中有4个参数(被操作对象,被操作属性,期望值,原始值)。
CAS有一个经典的问题ABA,值从A改成了B,B又改成了A,这个时候原始值是一样的,但是其实已经不再是之前的那个没改过之前的了,由此JAVA引入了AtomicStampedReference,在CAS时新增一个时间戳,比较时间戳是否一致。
悲观锁的场景有synchronized,Lock这些,我们常用的加锁都是悲观锁

Lock、AQS

Lock:java自带功能,是一个比synchronized轻量级的同步工具,通过state值来记录当前锁信息。Lock的核心实现是通过AQS来完成

ConcurrentHashMap

强调文本 强调文本

**

Guess you like

Origin blog.csdn.net/u012477338/article/details/108920344