📜  Java的ReentrantReadWriteLock 类(1)

📅  最后修改于: 2023-12-03 14:43:02.715000             🧑  作者: Mango

Java的ReentrantReadWriteLock 类

在Java中,ReentrantReadWriteLock 类是 java.util.concurrent.locks 包中的一个工具,其提供的读写锁可以让多个线程同时访问一个资源,而保证在写操作的时候只有一个线程在进行操作。

代码示例
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class MyClass {
  private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
  private final Object data = new Object();

  public void readData() {
    rwl.readLock().lock();
    try {
      // 读取data对象
      System.out.println("Read data: " + data);
    } finally {
      rwl.readLock().unlock();
    }
  }

  public void writeData(Object newData) {
    rwl.writeLock().lock();
    try {
      // 更新data对象
      data = newData;
      System.out.println("Write data: " + data);
    } finally {
      rwl.writeLock().unlock();
    }
  }
}
读写锁的特点
  • 可重入:同一个线程可以多次获取读锁或写锁,而不会被阻塞。
  • 公平性:可以选择公平锁或非公平锁,默认是非公平锁。公平锁可以确保等待时间最长的线程优先获得锁;非公平锁可能会让等待时间较短的线程优先获得锁,从而可能导致某些线程长时间得不到执行。
  • 支持多个读操作的同时进行,当写操作被执行时,所有的读操作将被阻塞,以实现数据的互斥访问。
实现原理

ReentrantReadWriteLock 的底层是基于 AQS(AbstractQueuedSynchronizer)实现的,其中 AQS 通过利用一个 FIFO 的等待队列和“state”属性来实现线程的阻塞、唤醒和互斥访问。

当一个线程获取读锁时,它会将 state 减去一个 SHARED_UNIT(等于 1),如果减之后 state 值不小于 0,则成功获取读锁。当一个线程获取写锁时,它将 state 减去一个 EXCLUSIVE_UNIT(等于 65536),如果减之后 state 值等于 0,则成功获取写锁,否则会加入等待队列并被阻塞,直到当前持有锁的线程释放锁。

注意事项
  • 当读写锁被使用时,应该尽可能地在写操作时获取写锁,而在读操作时获取读锁,以充分利用读写锁的并发性能。
  • 由于 ReentrantReadWriteLock 的实现方式,当读写锁被频繁占用时会有一定的性能消耗,因此在并发度较高的情况下应该慎用该锁。