Java多线程之Lock体系

发布于:2025-04-05 ⋅ 阅读:(10) ⋅ 点赞:(0)

Lock体系

Lock接口是什么?

Lock接口比同步方法和同步块提供了更具扩展性的锁操作.他们允许更灵活的结构,可以具有完全不同的性质,并且可以支持多个相关类的条件对象

优势:

  • 使锁更公平
  • 使线程在等待锁的时候响应中断
  • 可以让线程尝试获取锁,并在无法获取锁的时候立即返回或者等待一段时间
  • 可以在不同的范围,以不同的顺序获取和释放锁

整体来说,Lock就是synchronized的扩展版,Lock提供了无条件的,可轮询的(tryLock方法),定时的(tryLock带参方法),可中断的(lockInterruptibly),可多条件队列的锁操作.Lock的实现基本都支持非公平锁和公平锁,synchronized只支持非公平锁,当然在大多数情况下,非公平锁是高效的选择

Lock实现的子类有哪些?

  • ReadWriteLock
  • ReentrantLock
  • ReentrantReadWriteLock
  • StampedLock

乐观锁和悲观锁的理解以及如何实现?有哪些实现方式?

  • 悲观锁:总是很悲观的假设最坏的情况,每次拿数据的时候都认为别人会修改,所以在每次拿的时候都会上锁,这样别人想拿这个数据时就会阻塞,直到它拿到锁。(共享资源每次只给一个线程使用,其他线程阻塞等待,用完之后再把资源转让给其他资源)
    • 传统的关系型数据库里面很多都用到了这种锁机制,比如行级锁,表级锁,读锁,写锁等,都是在做操作之前先加锁,Java中的synchronized关键字的实现也是悲观锁
  • 乐观锁:总是很乐观的觉得,每次去拿数据的时候别人不会修改,所以不会上锁,在提交数据的时候才会检查数据是否被修改(产生并发冲突),如果被修改了,就返回错误信息。乐观锁一般适用于多读场景。一般使用版本号机制或者CAS实现

什么是AQS?

AQS——抽象的队列式的同步器,是一个用来构建锁和同步器的框架,使用AQS能简单且高效的构建出应用广泛的大量的同步器,比如ReentrantLock、Semaphore,其他诸如ReentrantReadWriteLock、SynchronousQueue、FutureTask等都是基于AQS的。

AQS实现了:对同步状态的管理,以及对阻塞线程进行排队,等待通知等一系列底层的实现

AQS原理分析

AQS的核心思想是:如果请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁的分配机制,这个机制是AQS使用CLH队列(虚拟的双向队列)锁实现的,将暂时获取不到锁的线程加入到队列中

AQS资源共享的方式

AQS底层定义了两种资源共享的方式:

  • Exclusive(独占):只有一个线程可以获取到资源,如ReentrantLock,又可以分为公平锁和非公平锁
    • 公平锁:按照线程在队列中的排列顺序,先到者先获取资源
    • 非公平锁:当线程要获取资源时,无视队列顺序,直接去抢锁,谁抢到就是谁的
  • Share(共享):多个线程可以同时执行;如Semaphore/CountDownLatch

什么是可重入锁(ReentrantLock)

ReentrantLock重入锁,是实现了Lock接口的一个类,支持重入性,表示能够对共享资源重复加锁,即当前线程获取到该锁之后再次获取不会被阻塞;

java中synchronized关键字隐式的支持重入性,synchronized关键字是通过monitor的计数器来自增实现

重入性的实现原理

  • 在线程获取锁的时候,如果已经获取锁的线程是当前线程的话则直接再次获取成功
  • 由于锁会被获取n次,那锁只有被释放n次之后,该锁才能算是被释放成功

公平锁与非公平锁

  • 公平锁每次获取到的都是同步队列中的第一个节点,保证了请求资源时间上的绝对顺序,非公平锁就是无视队列顺序,直接抢锁,可能会导致"饥饿";
  • 公平锁为了保证时间上的绝对顺序,需要频繁的切换上下文,而非公平锁会降低一定的上下文切换,降低性能开销.所以ReentrantLock默认选择的是非公平锁,保证系统有更大的吞吐量

独占锁和共享锁

  • 独占锁(Exclusive):只有一个线程可以持有线程同步状态
  • 共享锁(Share):多个线程可以持有线程同步状态

ReadWriteLock(读写锁)是什么?

ReadWriteLock是一个读写锁接口,读写锁是用来提升并发程序性能的锁分离技术,ReentrantReadWriteLock是ReadWriteLock接口的一个具体实现,实现了读写的分离,读锁是共享的,写锁是独占的,读与读之间是不会互斥的,读和写,写和读,写和写之间是互斥的,提升了读写的性能

读写锁有三个重要的特性:

  • 公平选择性:支持非公平(默认)和公平的锁获取方式,吞吐量还是非公平优于公平锁
  • 重入锁:读锁和写锁都是支持线程重入的
  • 锁降级:遵循获取写锁,获取读锁再释放写锁的顺序,写锁可以降级为