多线程中的锁机制(悲观锁/乐观锁/偏向锁/自旋锁(轻量级锁))

一、锁的分类及优化

  • 悲观锁
  • 乐观锁
  • 偏向锁
  • 自旋锁 (轻量级锁)
  • 重入锁
锁的优化:无锁→偏向锁→(轻量级锁)自旋锁→重量锁

1. 悲观锁:(synchronize锁就是悲观锁的体现)

1)简述
每次对数据的操作,都会担心数据被修改,每次操作时要对数据进行加锁,只有获取锁的线程才能操作该数据,操作该数据其他线程就会被阻塞

2)使用场景:写多读少
3)缺点:悲观锁的使用需要不断加锁,释放锁。这样会引起线程的上下文切换和延时调度,会影响系统性能, 未获取锁的线程会被阻塞住。

2.乐观锁:(CAS就是乐观锁的体现)CAS详情! 请点击…

1)简述
每次对数据的操作,都不会担心数据被修改,对数据进行读取操作不需要加锁
当更新数据时需要判断数据是否被修改,未被修改时则可以直接更新
2)使用场景:读多写少

3.偏向锁:

偏向锁的操作实际上没有去找操作系统。
每一个对象都有属于自己的对象头,其中有一个Mark Word当中有几个标识位和其他数据,如下图
锁的相关信息记录在对象头中
在这里插入图片描述
JVM使用CAS操作把线程ID记录到了Mark Word的数据中,修改了偏向和标识位,当前记录的线程就拥有了这把锁
在这里插入图片描述
从上图看出:JVM不用操作系统的介入,只记录线程ID,就能让当前线程拥有锁
当线程拥有的锁,就可以执行synchronized修饰的代码块,当线程再一次执行到Synchronized的时候,JVM通过Mark word判断,当前 线程ID还在,并且还持有这个对象的锁,就可以继续进入临界区执行代码。在没有别的线程竞争的时候,锁一直偏向这个线程,当前线程可以一直执行下去。

4.自旋锁(轻量级锁):

JVM把对象恢复成无锁状态,在当前两线程的栈帧中各自分配了一个空间,叫做Lock Record,把锁对象的Mark word在两个线程的栈帧中各自复制了一份,叫做Displaced Mark,然后当前线程的 Lock Record的地址使用CAS放到了 Mark word中,并把锁标志位改成了00,这表示当前线程已经获得了这个轻量级锁,可以进入临界区执行。
在这里插入图片描述
若线程没有获得锁,JVM会让它自旋几次,等待一会,等当前退出临界区,释放锁的时候,需要把**Displaced Mard word **使用CAS复制回去,然后就可以加锁了。
两个线程交替进入临界区执行这一段代码,很少会出现竞争。
在这里插入图片描述

5.重入锁:ReenTrantLock JDK剖析可重入锁详情,请点击…

  • 特征: 可中断响应,锁限时操作,公平锁,结合Condition使用
  • 使用
 ReentrantLock lock = new ReentrantLock(true);
 lock.lock();
 try{
 //操作
    }finally{
     lock.unlock();
     }
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值