天增的博客
首页
博客
  • 分布式解决方案
  • Java并发工具包
  • redis
  • LeetCode
  • 系统设计
  • JVM体系
Github (opens new window)
Rss (opens new window)
  • zh-CN
  • en-US
首页
博客
  • 分布式解决方案
  • Java并发工具包
  • redis
  • LeetCode
  • 系统设计
  • JVM体系
Github (opens new window)
Rss (opens new window)
  • zh-CN
  • en-US
  • Java并发工具包
  • 并发基础
    • 线程基础
      • Thread的状态
      • 进程与线程
      • 正确停止线程的方式
      • Thread的实现方式
      • waitnotifynotifyAll
      • 生产者消费者模型
    • 线程安全
      • 线程不安全
      • 线程安全
      • 需要注意线程安全问题的情况
  • 并发工具
    • 线程协作
      • Semaphore信号量
      • CountDownLatch详解
      • 使用CompletableFuture解决旅游平台问题
      • 使用CyclicBarrier解决团建问题
    • Future
      • Future主要功能
      • FutureTask源码分析
    • ThreadLocal
      • ThreadLocal内存泄漏
      • ThreadLocal使用场景
    • 原子类
      • 原子类的作用概览
      • 原子类的性能分析
    • 阻塞队列
      • 常见的阻塞队列
      • 阻塞队列的常用方法
      • 什么是阻塞队列
    • 并发容器
      • HashMap
      • CopyOnWriteArrayList
      • ConcurrentHashMap详解
    • 线程池
      • 为什么多线程会带来性能问题
      • 线程池的优势
      • 创建线程池的参数
        • 如何设置线程数
      • 线程池线程复用原理
      • ForkJoin框架
    • 各种锁
      • 锁的种类和特点
        • 公平锁非公平锁
        • 自旋锁非自旋锁
        • 共享锁独占锁
        • 乐观锁和悲观锁
      • JVM锁优化
      • synchronized和Lock的对比
      • lock的常用方法
  • 底层原理
    • CAS原理
    • AQS框架
    • 伪共享
    • java内存模型
      • Java内存模型介绍
      • happens-before规则
  • topic
  • Java并发工具包
  • 并发工具
  • 各种锁
  • 锁的种类和特点
2022-04-21
目录

锁的种类和特点

# 锁的种类和特点

锁的种类有七种

  1. 偏向锁/轻量级锁/重量级锁
  2. 可重入锁/不可重入锁
  3. 共享锁/独占锁
  4. 公平锁/非公平锁
  5. 乐观锁/悲观锁
  6. 自旋锁/非自旋锁
  7. 可中断锁/不可中断锁

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

这三种是JVM为了提升synchronized修饰的方法的并发性能,而出现的锁。

实现方式是通过对象头中的mark word 字段,来表明锁的状态。

  • 偏向锁

    偏向锁指的是,如果一段代码的并发程度很低,只有一个线程在请求锁,那么其实就没有必要上锁,JVM的做法是,当一个对象被初始化之后,这个时候就是可偏向的,在第一个线程访问锁的时候会在这个对象标记上线程的信息,那么在下一次还是这个线程请求,就直接获取到锁,开销比较小,性能好

  • 轻量级锁

    轻量级锁,synchronized修饰的方法被多个线程访问,就会从偏向锁升级成轻量级锁。因为在绝大多数的情况下,线程都是交替执行只存在于少量的竞争,这个时候轻量级锁会通过CAS方式进行自旋,不会陷入到阻塞

  • 重量级锁

    重量级锁,是在操作系统层实现的一个完全互斥的锁。当有多个线程在竞争,且竞争的时间过长的时候,轻量级锁就会膨胀成重量级锁。重量级锁会让其他没有获取到锁的线程进入阻塞状态。

所以,synchronized的锁是会经历 无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁 这几个过程,这个过程也被称之为锁的膨胀。

其中,偏向锁性能最好,轻量级锁由于CAS自旋,所以性能次之,重量级锁存在线程的阻塞和唤醒,性能最差。

# 可重入锁/不可重入锁

可重入锁是指,在线程当前已经持有这把锁了,在不释放这把锁的情况下,再次获取这把锁。

不可重入锁是指,在线程当前已经只有这把锁了,必须得先释放掉持有的锁,才能够重新获取锁。

对于可重入锁而言,最典型的就是 ReentrantLock 了,正如它的名字一样,reentrant 的意思就是可重入,它也是 Lock 接口最主要的一个实现类。

# 共享锁/独占锁

最好能够全是共享锁和独占锁的是读写锁。读文件的时候,可以多个线程读取一个文件,但是在写入的时候只允许一个线程进行写入。

当读写锁是写加锁状态时, 在这个锁被解锁之前, 所有试图对这个锁加锁的线程都会被阻塞.

当读写锁在读加锁状态时, 所有试图以读模式对它进行加锁的线程都可以得到访问权, 但是如果线程希望以写模式对此锁进行加锁, 它必须直到所有的线程释放锁.

通常, 当读写锁处于读模式锁住状态时, 如果有另外线程试图以写模式加锁, 读写锁通常会阻塞随后的读模式锁请求, 这样可以避免读模式锁长期占用, 而等待的写模式锁请求长期阻塞.

# 公平锁/非公平锁

公平锁是指,在线程拿不到锁的时候会进入到等待,开始排队,在队列中等待时间长的会优先分配到锁,先来先得。

非公平锁是指,在线程拿不到锁的时候,开始排队,但是分配上是会忽略掉排队时间,随机分配到一个线程上

# 乐观锁/悲观锁

悲观锁在获取到资源之前,必须先拿到锁,JVM的重量级锁就是一种悲观锁,只有在独占锁的时候,才回去操作资源。

乐观锁在获取资源之前无需拿到锁,只有在最后更新的时候,会通过CAS的方式去更新资源,JVM的轻量级锁与之类似

# 自旋锁/非自旋锁

自旋锁的理念是如果线程现在拿不到锁,并不直接陷入阻塞或者释放 CPU 资源,而是开始利用循环,不停地尝试获取锁,这个循环过程被形象地比喻为“自旋”,就像是线程在“自我旋转”。相反,非自旋锁的理念就是没有自旋的过程,如果拿不到锁就直接放弃,或者进行其他的处理逻辑,例如去排队、陷入阻塞等。

# 不可中断锁/可中断锁

在 Java 中,synchronized 关键字修饰的锁代表的是不可中断锁,一旦线程申请了锁,就没有回头路了,只能等到拿到锁以后才能进行其他的逻辑处理。而我们的 ReentrantLock 是一种典型的可中断锁,例如使用 lockInterruptibly 方法在获取锁的过程中,突然不想获取了,那么也可以在中断之后去做其他的事情,不需要一直傻等到获取到锁才离开。

最近更新
01
以 root 身份启动 transmission-daemon
12-13
02
Debian系统安装qbittorrent-nox
12-09
03
LXC Debain12安装zerotier并实现局域网自动nat转发
07-29
更多文章>
Theme by Vdoing | Copyright © 2015-2024 天增 | 苏ICP备16037388号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式