ReentrantLock、ReentrantReadWriteLock、StampedLock讲解

简介: ReentrantLock、ReentrantReadWriteLock、StampedLock讲解

1. 概述

多线程编程中,锁是必不可少的,因为许多并发问题都可以通过加锁来解决,例如线程安全的单例实现、线程安全的数据结构实现等等。Java提供了许多类型的锁,本文就来介绍其中三种常见的锁:ReentrantLock、ReentrantReadWriteLock、StampedLock。

2. ReentrantLock

2.1 基本概念

ReentrantLock(重入锁)是Java中的一个独占锁,也是一种可重入锁。独占锁是指同一时刻只能有一个线程获得锁,其他线程必须等待;可重入锁是指线程可多次获取同一把锁,不会自己阻塞自己。

2.2 使用方法

使用ReentrantLock的基本方法如下:

ReentrantLock lock = new ReentrantLock(); // 创建锁对象
lock.lock(); // 获取锁
try {
    // 执行需要加锁的代码
} finally {
    lock.unlock(); // 释放锁
}

在上面的代码中,首先创建一个ReentrantLock对象,然后在需要加锁的代码执行前调用lock()方法获取锁,在需要释放锁的地方使用unlock()方法释放锁。

需要注意的是,在使用ReentrantLock时,要保证锁的获取和释放要在try…finally块中进行。因为在试图获取锁的过程中,如果线程被中断(interrupt),那么当前线程也需要释放锁资源。

2.3 特性

ReentrantLock有一些特性:

  • 重入性:同一个线程可以反复获取同一把锁,不会造成死锁。
  • 公平锁和非公平锁:ReentrantLock提供了两种获取锁的方式:公平锁和非公平锁。公平锁是指等待时间最长的线程优先获取锁,而非公平锁是指线程直接尝试获取锁,如果失败了才会进入等待队列。默认情况下,ReentrantLock是非公平锁。
  • 可中断:ReentrantLock提供了可中断的获取锁的方式,即在等待锁的过程中,如果线程被中断,则会抛出InterruptedException异常。在使用可中断获取锁的方式时,需要捕获InterruptedException异常。
  • 条件变量:ReentrantLock中可以使用Condition对象来实现线程间的通信与同步。Condition对象和锁对象是绑定在一起的,一个锁对象可以创建多个Condition对象,用于不同的等待队列。常见的方法有await()、signal()和signalAll()。

2.4 总结

ReentrantLock是一种可重入锁,提供了公平锁和非公平锁、可中断获取锁和条件变量等特性,使用起来比较灵活,但也比较复杂,需要手动控制加锁和释放锁的过程。

3. ReentrantReadWriteLock

3.1 基本概念

ReentrantReadWriteLock(可重入读写锁)是Java中另一种常用的锁,也是一种可重入锁。与ReentrantLock不同的是,ReentrantReadWriteLock既可以支持独占锁,也可以支持共享锁。共享锁是指同一时刻可以有多个线程读取共享资源,但只能有一个线程写入共享资源;独占锁是指同一时刻只能有一个线程获得锁,其他线程必须等待。因此,ReentrantReadWriteLock适用于读多写少的场景,可以提高并发读操作的效率。

3.2 使用方法

使用ReentrantReadWriteLock的基本方法如下:

ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); // 创建锁对象
lock.readLock().lock(); // 获取读锁
try {
    // 执行需要读取共享资源的代码
} finally {
    lock.readLock().unlock(); // 释放读锁
}

在上面的代码中,首先创建一个ReentrantReadWriteLock对象,然后在需要读取共享资源的代码执行前调用readLock().lock()方法获取读锁,在需要释放锁的地方使用readLock().unlock()方法释放读锁。

如果需要写入共享资源,则需要获取写锁,相应地,释放锁时需要调用writeLock().unlock()方法。

需要注意的是,在使用ReentrantReadWriteLock时,要保证读锁和写锁的获取和释放要在try…finally块中进行。

3.3 特性

ReentrantReadWriteLock有一些特性:

  • 重入性:同一个线程可以反复获取同一把锁,不会造成死锁。
  • 公平锁和非公平锁:ReentrantReadWriteLock提供了公平锁和非公平锁,与ReentrantLock类似。默认情况下,ReentrantReadWriteLock是非公平锁。
  • 支持读写分离:ReentrantReadWriteLock支持读写分离,提高并发读的效率,并且不会阻塞读和读之间的操作。
  • 降低锁的粒度:ReentrantReadWriteLock可以将锁的粒度降低,提高并发度。
  • 可重入:ReentrantReadWriteLock是可重入的。

3.4 总结

ReentrantReadWriteLock是一种可重入读写锁,适用于读多写少的场景,提供了公平锁和非公平锁、支持读写分离、降低锁的粒度等特性。使用起来比ReentrantLock稍微复杂一些,但也比较灵活。

4. StampedLock

4.1 基本概念

StampedLock(标记锁)是Java 8中新增的锁机制。它是一种乐观锁,允许多个线程在没有互相干扰的情况下访问共享资源。相比于ReentrantLock和ReentrantReadWriteLock,StampedLock更适用于读多写少、并发度高的场景,也可以用于提高读操作的性能。

4.2 使用方法

StampedLock的基本使用方法如下:

StampedLock lock = new StampedLock(); // 创建锁对象
long stamp = lock.tryOptimisticRead(); // 尝试获取乐观读锁
// 执行读操作
if (lock.validate(stamp)) {
    // 检查是否可用
    // 执行读操作
} else {
    // 尝试获取悲观读锁
    stamp = lock.readLock(); // 获取悲观读锁
    try {
        // 执行读操作
    } finally {
        lock.unlockRead(stamp); // 释放悲观读锁
    }
}

在上面的代码中,首先创建一个StampedLock对象,然后使用tryOptimisticRead()方法尝试获取乐观读锁。如果获取成功,则可以执行读操作;如果获取失败,则需要使用读锁(悲观锁)来获取资源。在获取锁后,执行完读操作后需要释放锁。

StampedLock还提供了其他类型的锁,如悲观读锁、写锁等。使用方法和ReentrantReadWriteLock类似。


相关文章
ReentrantReadWriteLock读写锁
ReentrantReadWriteLock读写锁
|
2月前
|
Java 开发者
深入解析ReentrantLock与StampedLock的使用技巧
选择 `ReentrantLock`还是 `StampedLock`,应基于具体的应用场景。如果你的应用中读操作远多于写操作,并且希望利用乐观读锁来提高并发性能,那么 `StampedLock`是一个不错的选择。反之,如果你需要更复杂的锁行为,如公平性控制、条件变量或是需要响应中断的锁操作,则 `ReentrantLock`可能更加合适。理解每种锁的特点,并合理应用,是提升Java并发程序性能的关键。
19 3
|
7月前
|
缓存 测试技术
ReentrantReadWriteLock 读写锁
ReentrantReadWriteLock 读写锁
46 0
|
3月前
|
安全 Java
JUC锁: ReentrantReadWriteLock详解
`ReentrantReadWriteLock` 主要用于实现高性能的并发读取,而在写操作相对较少的场景中表现尤为突出。它保证了数据的一致性和线程安全,在合适的场合合理使用 `ReentrantReadWriteLock`,可以实现更加细粒度的控制,并显著提升应用性能。然而,需要注意它的复杂度较一般的互斥锁高,因此在选择使用时要仔细考虑其适用场景。
41 1
|
5月前
ReentrantLock 可重入锁总结
ReentrantLock 可重入锁总结
42 0
|
7月前
|
安全
深入ReentrantReadWriteLock
深入ReentrantReadWriteLock
56 7
深入ReentrantReadWriteLock
ReentrantLock和Synchronized简单比较
ReentrantLock和Synchronized简单比较
49 0
|
缓存 Java Linux
ReentrantLock、ReentrantReadWriteLock、StampedLock
ReentrantLock、ReentrantReadWriteLock、StampedLock
ReentrantLock、ReentrantReadWriteLock、StampedLock
|
Java
彻底理解ReentrantLock可重入锁的使用
java除了使用关键字synchronized外,还可以使用ReentrantLock实现独占锁的功能。而且ReentrantLock相比synchronized而言功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景。这篇文章主要是从使用的角度来分析一下ReentrantLock。
215 0
彻底理解ReentrantLock可重入锁的使用
|
uml
除了读写锁,JUC 下面还有个 StampedLock!还不过来了解一下么?
在了解完 ReentrantLock 和 ReentrantReadWriteLock 之后,惊奇的发现 JUC 下还有一个 StampedLock 。 查阅资料发现是 JDK8 新增的一个锁。现在已经 JDK15 了,原谅我的孤陋寡闻,实在是业务开发中用的太少。那行吧,赶紧来看一下 StampedLock 到底是什么?为什么有了 ReentrantLock 和 ReentrantReadWriteLock 之后还要设计一个 StampedLock ?
127 0