【912、ReentrantReadWriteLock 和 StampedLock】

80 阅读2分钟

ReentrantReadWriteLockStampedLock 都是 Java 中用于多线程并发控制的类,它们允许在多个线程之间安全地管理对共享资源的访问。这两个类都用于解决读-写锁问题,但它们有不同的特点和适用场景。

  1. ReentrantReadWriteLock

    • ReentrantReadWriteLock 是一个可重入的读写锁,意味着线程可以多次获取相同类型的锁而不会造成死锁。
    • 它提供了两种锁:读锁(共享锁)和写锁(独占锁)。
    • 多个线程可以同时获取读锁,只有一个线程可以获取写锁。
    • 当某个线程持有写锁时,其他线程无法获取读锁或写锁,这有助于避免写-写冲突。
    • ReentrantReadWriteLock 使用了内部计数器来追踪读锁的持有次数,从而允许同一线程重复获取读锁。
import java.util.concurrent.locks.ReentrantReadWriteLock;

ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
rwLock.readLock().lock(); // 获取读锁
rwLock.writeLock().lock(); // 获取写锁
  1. StampedLock

    • StampedLock 也是一个支持读-写锁的类,但它引入了更灵活的乐观读(optimistic reading)模式。
    • ReentrantReadWriteLock 不同,StampedLock 不支持可重入性,同一线程不能多次获取写锁,否则会导致死锁。
    • StampedLock 的乐观读模式允许线程在不阻塞其他线程的情况下尝试读取数据,然后检查是否被其他线程修改。
    • 乐观读失败后,线程可以回退到悲观读模式(与普通的读锁类似)。
    • StampedLock 对于读操作非常高效,但写操作的效率可能不如 ReentrantReadWriteLock
import java.util.concurrent.locks.StampedLock;

StampedLock stampedLock = new StampedLock();
long stamp = stampedLock.readLock(); // 获取悲观读锁
long stamp = stampedLock.writeLock(); // 获取写锁

选择使用哪个锁取决于你的具体需求。如果你需要可重入性和更简单的读写锁,可以使用 ReentrantReadWriteLock。如果你需要更高的读取性能和支持乐观读的特性,可以考虑使用 StampedLock。但要注意,在某些情况下,错误使用 StampedLock 可能会导致性能下降或死锁问题,因此需要谨慎使用。