总结篇(30)---Java并发及锁(4)常见锁及分类

本文详细介绍了Java中的多种锁机制,包括公平锁与非公平锁、可重入锁与不可重入锁、独享锁与共享锁等,并探讨了乐观锁与悲观锁的不同应用场景。此外还解释了分段锁、自旋锁、可中断锁的概念及其适用场景。

一、公平锁和非公平锁


  • 公平锁:指多个线程按照申请锁的顺序来获取锁
  • 非公平锁:没有顺序完全随机,所以会造成优先级反转


        举例:
            synchronized就是非公平锁
            ReentrantLock(使用CAS和AQS实现)通过构造参数可以决定是非公平锁还是公平锁,默认构造是非公平锁,非公平锁的吞吐量性能比公平锁大好。

 


二、可重入锁和不可重入锁


  • 可重入锁:又名递归锁,指同一线程在外层方法获取锁的时候进入内层方法会自动获取锁
  • 不可重入锁:即当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞。


        举例:
            synchronized和ReentrantLock都是可重入锁,可重入锁可以在一定程度上避免死锁。
            不可重入锁目前没遇到过。
            


三、独享锁和共享锁


  • 独享锁:指该锁一次只能被一个线程持有
  • 共享锁:指该锁可以被多个线程所持有


        举例:
            synchronized和ReentrantLock都是独享锁
            ReadWriteLock的读锁是共享锁,写锁是独占锁(ReadWriteLock是一个接口,实现类有ReetrantReadWriteLock)
            


 四、乐观锁和悲观锁


这个分类不是具体锁的分类,而是看待并发同步的角度。

  • 乐观锁:认为对于同一数据的并发操作是不会发生修改的,在更新数据的时候会采用不断的尝试更新,乐观锁认为不加锁的并发操作是没事的。
  • 悲观锁:认为对于同一个数据的并发操作一定是会发生修改的(哪怕实质没修改也认为会修改),因此对于同一个数据的并发操作,悲观锁采取加锁的形式,因为悲观认为不加锁的操作一定有问题。


        乐观锁适合 读操作 非常多的场景,不加锁会带来大量的性能提升,乐观锁就是基于CAS的无锁编程。如java的原子类就是通过CAS自旋实现的。
        悲观锁适合 写操作 非常多的场景。

 


五、分段锁


实际上一种锁的策略,不是具体的锁。

  • 分段锁的设计是为了细化锁的粒度。


        举例:
            jdk1.7的ConcurrentHashMap的实现就是通过分段锁的形式来实现高效并发操作。
            当要put元素时并不是对整个hashmap加锁,而是先通过hashcode知道它要放在哪个分段,然后对分段进行加锁,所以多线程put元素时只要放在的不是同一个分段就做到了真正的并行插入,但是统计size时就需要获取所有的分段锁才能统计。


六、偏向锁、轻量级锁、重量级锁


这几种状态都不是java语言中的锁,而是jvm为了提高锁的获取与释放而做的优化(使用synchronized时)

  • 偏向锁:

一段同步代码一直被一个线程所访问,那么该线程就会自动获取锁。降低获取锁的代价。

 

  • 轻量级锁:

指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。

  • 重量级锁:

指当锁为轻量级锁的时候,另一个线程虽然自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低。


        其实一共有四种状态,分别是无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态。
        锁的状态是通过对象监视器在对象头中的字段来声明的。
        这四种状态会随着竞争的情况逐渐升级,而且是不可逆的过程,即不可降级。
备注:
锁的状态在对象头中怎么标记声明,这个有需要的时候再进行补充,暂时不深究。

 

七、自旋锁


  • 自旋锁的线程一直是RUNNABLE状态的,一直在那循环检测锁标志位,但是全程消耗cpu。起始开销虽然低于互斥锁,但随着持锁时间加锁开销是线性增长。


        其实自旋锁的概念是相对于互斥锁的概念,互斥锁线程会进入WAITING状态和RUNNABLE状态的切换,涉及上下文切换、cpu抢占等开销。

 

八、可中断锁


  • 就是可以中断的锁

        synchronized是不可中断的,Lock是可中断的,这里的中断建立在阻塞等待中断,运行中是无法中断的。

 

更多java基础总结(适合于java基础学习、java面试常规题):

总结篇(1)---复用类

总结篇(2)---多态

总结篇(3)---内部类 (1)内部类的基本概念

总结篇(4)---内部类 (2)内部类之静态内部类

总结篇(5)---内部类 (3)内部类之成员内部类

总结篇(6)---内部类 (4)内部类之局部内部类

总结篇(7)---内部类 (5)内部类之匿名内部类

总结篇(8)---序列化

总结篇(9)---字符串及基本类 (1)字符串及基本类之基本数据类型

总结篇(10)---字符串及基本类 (2)字符串及基本类之java中公共方法及操作

总结篇(11)---字符串及基本类 (3)String对象

总结篇(12)---字符串及基本类 (4)Integer对象

总结篇(13)--- Java注解及元注解

总结篇(14)---JVM(java虚拟机) (1)JVM虚拟机概括

总结篇(15)---JVM(java虚拟机) (2)类加载器

总结篇(16)---JVM(java虚拟机) (3)运行时数据区

总结篇(17)---JVM(java虚拟机) (4)垃圾回收

总结篇(18)---JVM(java虚拟机) (5)垃圾回收算法

总结篇(19)---JVM(java虚拟机) (6)JVM调优

总结篇(20)---反射

总结篇(21)---Java IO

总结篇(22)---Java 进程

总结篇(23)---Java线程及其相关(1)线程介绍

总结篇(24)---Java线程及其相关(2)多线程及其问题

总结篇(25)---Java线程及其相关(3)线程池及其问题

总结篇(26)---Java线程及其相关(4)ThreadLocal

总结篇(27)---Java并发及锁(1)Synchronized

总结篇(28)---Java并发及锁(2)Volatile

总结篇(29)---Java并发及锁(3)Lock

总结篇(30)---Java并发及锁(4)常见锁及分类

总结篇(31)---JUC工具类(1)CountDownLatch

总结篇(32)---JUC工具类(2)CyclicBarrier

总结篇(33)---JUC工具类(3)Semaphore

总结篇(34)---JUC工具类(4)Exchanger

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sun cat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值