Java中涉及到的各种锁——自旋锁、阻塞锁、可重入锁等等

锁的作用

锁是作为共享数据保证数据一致性的工具,在并发情况使用。在Java平台中有多种锁的实现比如Synchronize和ReentrantLock。
按照锁的类型可以分为以下几种:

  1. 自旋锁
  2. 阻塞锁
  3. 可重入锁 / 不可重入锁
  4. 独享锁 / 共享锁
  5. 偏向锁 / 轻量锁 / 重量锁

从宏观上分类又可以分为:乐观锁和悲观锁


自旋锁

自旋锁原理非常简单,如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,它们只需要等一等(自旋),等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换的消耗。

但是线程自旋是需要消耗cup的,说白了就是让cup在做无用功,如果一直获取不到锁,那线程也不能一直占用cup自旋做无用功,所以需要设定一个自旋等待的最大时间。

如果持有锁的线程执行的时间超过自旋等待的最大时间扔没有释放锁,就会导致其它争用锁的线程在最大等待时间内还是获取不到锁,这时争用线程会停止自旋进入阻塞状态。

自旋锁的优缺点:

优点: 自旋锁尽可能的减少线程的阻塞,这对于锁的竞争不激烈,且占用锁时间非常短的代码块来说性能能大幅度的提升,因为自旋的消耗会小于线程阻塞挂起再唤醒的操作的消耗,这些操作会导致线程发生两次上下文切换

缺点:自旋锁的缺点很明显就是容易造成CPU的空转,因为自旋是一直占着CPU做无用功的,所以如果锁的竞争很激烈,并且每个线程需要的执行时间占用锁的时间很长,就不适合用自旋锁。

改进方法:给自旋锁设定一个超时时间,超过这个时间还未能获得锁的时候,线程阻塞进入等待队列。

阻塞锁

与自旋锁对应,阻塞锁不会进行自旋,而是进入阻塞状态。当获得相应的信号(被外界唤醒、到休眠时间)时,线程进入就绪态,继续竞争临界资源。
JAVA中,能够进入\退出、阻塞状态或包含阻塞锁的方法有 ,synchronized 关键字(其中的重量锁),ReentrantLock,Object.wait()、notify(), LockSupport.park()、unpart() (j.u.c经常使用) 。
优缺点
优点:阻塞的线程不会占用CPU太多时间,不会有CPU空转的情况,不会导致CPU占用率过高。竞争激烈的情况下,性能明显高于自旋锁。
缺点:竞争不激烈的情况下,线程的切换会浪费太多时间。

可重入锁 / 不可重入锁

可重入锁:也叫递归锁,指的是同一线程外层函数得到锁后,内层递归函数仍然可以获得该锁。Java中ReentranLock和Synchronize都是可重入锁。
可重入锁的最大作用是避免死锁
不可重入锁:和可重入锁相反,就是线程不可重入的意思,一个线程持有某个锁,如果再去请求一次这个锁,则有可能造成死锁。

独享锁/ 共享锁

独享锁:顾名思义该锁是单独具有的,一次只能给一个线程持有。一般涉及到写操作的,只能是独享锁
共享锁:锁是共享的,可以同时被多个线程持有。多个线程同时进行读操作可以用共享锁。

偏向锁/轻量级锁/重量级锁

锁的状态主要有:无锁状态 --> 偏向锁状态 --> 轻量锁状态 --> 重量锁状态。锁的状态是通过对象监视器在对象头中的字段来表明的,四种情况会随着竞争情况逐渐升级,而且是不可逆的
偏向锁:偏向锁是指同一段同步代码一直被一个线程锁访问,那么这个线程会自动获取锁,降低获取锁的代价。
轻量级锁:轻量锁是指当前锁是偏向锁的时候,被另一个线程访问,偏向锁会升级为轻量级锁。其他线程会通过自的形式尝试获取锁,提高性能。
重量级锁:重量级锁是指当锁为轻量级锁的时候,另一个线程是自旋,但是不会一直自旋下去。当自旋一定次数或一定时间(超时)还未能获取锁,线程进入阻塞状态。此时该锁膨胀为重量锁,重量锁会让其他线程进入阻塞状态,性能降低。

乐观锁 / 悲观锁

乐观锁:乐观向上,总是假设情况都是最好的,每次去拿数据的时候认为别人修改数据所以不会加锁,但是更新的时候会判断一下数据有没有被其他线程更新过。乐观锁适用于多读的应用类型,可以提应用高吞吐量。数据库提供的类似write_condition 机制其实就是提供乐观锁。
悲观锁:悲观消极,每次都假设最差的情况。每次去拿数据的时候都会加锁,因为它会假设别人会对数据进行修改,所以先加锁保证数据一致性。Synchronize和ReentranLock等独占锁使用的就是悲观锁思想

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值