Skip to content

StampedLock接口是Java 8中引入的一种读写锁机制。它提供了一种乐观读取和悲观读/写锁的实现方式。

与传统的读写锁(如ReentrantReadWriteLock)相比,StampedLock具有更高的并发性能和灵活性。它适用于读操作非常频繁而写操作较少的场景。

下面是StampedLock接口的几个主要方法:

  • long readLock(): 获取一个悲观读锁,并返回一个标记值(stamp),如果没有其他线程持有写锁,则立即返回;否则会阻塞等待。
  • long tryReadLock(): 尝试获取一个悲观读锁,如果成功则返回一个标记值,如果失败则立即返回0,不会阻塞。
  • void unlockRead(long stamp): 释放一个悲观读锁。
  • long writeLock(): 获取一个写锁,并返回一个标记值,如果没有其他线程持有读锁或写锁,则立即返回;否则会阻塞等待。
  • long tryWriteLock(): 尝试获取一个写锁,如果成功则返回一个标记值,如果失败则立即返回0,不会阻塞。
  • void unlockWrite(long stamp): 释放一个写锁。
  • long tryOptimisticRead(): 尝试获取一个乐观读锁,返回一个标记值,不会阻塞。乐观读锁不提供线程安全性保证,需要结合验证操作来确保数据的一致性。
  • boolean validate(long stamp): 验证标记值对应的锁是否仍然有效。

使用StampedLock时需要注意以下几点:

  • 你可以同时拥有一个悲观读锁和一个写锁,但不能同时拥有多个写锁。
  • 在使用乐观读锁后,需要通过调用validate()方法来验证标记值是否仍然有效,并且在验证失败时重新获取悲观读锁或写锁。
  • StampedLock是非重入锁,即同一个线程在持有锁的情况下再次请求该锁会导致死锁。

这里是一个简单示例代码,演示了如何使用StampedLock实现读写锁:

import java.util.concurrent.locks.StampedLock;

public class StampedLockExample {
    private double x, y;
    private final StampedLock lock = new StampedLock();

    public void write(double newX, double newY) {
        long stamp = lock.writeLock();
        try {
            x = newX;
            y = newY;
        } finally {
            lock.unlockWrite(stamp);
        }
    }

    public double read() {
        long stamp = lock.tryOptimisticRead();
        double currentX = x;
        double currentY = y;
        if (!lock.validate(stamp)) {
            stamp = lock.readLock();
            try {
                currentX = x;
                currentY = y;
            } finally {
                lock.unlockRead(stamp);
            }
        }
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }
}

在上面的示例中,write()方法使用写锁来更新x和y的值,而read()方法则使用乐观读锁(如果验证失败,则转为悲观读锁)来读取xy的值,并计算其平方和。