关于java:深入分析-Java-Lock-同步锁

7次阅读

共计 1842 个字符,预计需要花费 5 分钟才能阅读完成。

前言

Java 的锁实现,有 Synchronized 和 Lock。上一篇文章深入分析了 Synchronized 的实现原理:由 Java 15 废除偏差锁,谈谈 Java Synchronized 的锁机制。

本篇文章深入分析 Lock 的实现,以及比照其与 Synchronized 的不同。

Synchronized 与 Lock 的比照

  • 实现形式:Synchronized 由 JVM 实现;Lock 由 Java 底层代码实现
  • 锁获取:Synchronized 是 JVM 隐式获取,不必 Java 代码;Lock 由 Java 代码实现,有多种获取形式
  • 锁的开释:Synchronized 是 JVM 隐式开释,不必 Java 代码;Lock 可通过 Lock.unlock(),在 finally 中开释
  • 锁的类型:Synchronized 是非偏心、可重入的Lock 是非公平性、公平性、可重入的
  • 锁的中断:Synchronized 不反对中断,Lock 反对中断

实现原理

Lock 是一个接口类,其接口办法定义:

  • lock():获取锁
  • lockInterruptibly():如果以后线程未被中断,则获取锁,能够响应中断
  • tryLock():仅在调用时锁为闲暇状态才获取该锁,能够响应中断
  • tryLock(long time, TimeUnit unit):如果锁在给定的等待时间内闲暇,并且以后线程未被中断,则获取锁
  • unlock():开释锁
  • newCondition():返回绑定到此 Lock 实例的新 Condition 实例

根底原理就不赘述了,Lock 接口的罕用类:

  • ReentrantLock(重入锁)
  • ReentrantReadWriteLock(可重入的读写锁)

其都是依赖 AQS 实现的。AQS 类构造中蕴含一个 基于链表实现的期待队列(CLH 队列),用于存储所有阻塞的线程,AQS 中还有一个 state 变量,示意加锁状态。

ReentrantLock

ReentrantReadWriteLock

ReentrantLock 是独占锁,对于同一份数据,如果一个线程读数据,另一个线程在写数据,那么读到的数据与最终的数据可能不统一。

在理论的业务场景中,读操作远远大于写操作。在多线程编程中,读操作不会批改共享资源的数据。针对读多写少的场景,咱们能够应用 ReentrantReadWriteLock 来优化,ReentrantReadWriteLock 外部保护了 2 个锁:读锁 ReadLock,写锁 WriteLock

规定简略概括为:

  • 如果写锁没有被占用,就能够获取读锁
  • 如果读锁没有被占用,才能够获取写锁

上面的测试代码,因为读锁和写锁是同时 lock 的,所以会死锁。

@Test
public void testReadWriteLock() {ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    lock.readLock().lock();
    lock.writeLock().lock();
    System.out.println("Hello");
    lock.readLock().unlock();
    lock.writeLock().unlock();
}

StampedLock

上述 ReentrantReadWriteLock 会有一个问题:在读很多,写很少的状况下,线程会因始终无奈获取到锁而处于期待状态。

在 JDK 1.8 中,Java 提供了 StampedLock,有三种模式:

  • 乐观读
  • 乐观读

一个写线程获取写锁,通过 WriteLock 获取票据 stamp,WriteLock 是一个独占锁,unlockWrite 须要传递参数 stamp。

不一样的中央在于读过程。线程会先通过乐观锁 tryOptimisticRead 获取票据 stamp,如果以后没有线程持有写锁,则会返回一非 0 的 stamp 信息。线程获取该 stamp 后,会拷贝一份共享资源到房倒退。

之后办法还须要调用 validate,验证之前调用 tryOptimisticRead 返回的 stamp 在以后是否有其它线程持有了写锁,如果是,那么 validate 会返回 0,降级为乐观锁;否则就能够应用该 stamp 版本的锁对数据进行操作。

总结

相比于 Synchronized 同步锁,Lock 实现的锁更加灵便:

  • 能够分为读写锁,优化读大于写的场景
  • 能够中断
  • 能够超时
  • 能够辨别公平性

公众号

coding 笔记、点滴记录,当前的文章也会同步到公众号(Coding Insight)中,心愿大家关注 ^_^

代码和思维导图在 GitHub 我的项目中,欢送大家 star!

正文完
 0