Java并发编程之ReentrantReadWriteLock


基本使用方法

  1. 创建锁对象
    首先,通过 new ReentrantReadWriteLock() 创建一个锁实例。

  2. 获取读锁和写锁
    使用 readLock() 方法获得读锁对象,使用 writeLock() 方法获得写锁对象。

  3. 使用锁保护共享资源
    在需要保护的代码块前后分别调用 lock()unlock() 方法,确保对共享资源的访问安全。

示例代码:

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    // 分别获取读锁和写锁
    private final ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
    private final ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
    
    private int sharedData = 0;

    // 使用读锁保护读操作
    public int read() {
        readLock.lock();
        try {
            // 模拟读取操作
            return sharedData;
        } finally {
            readLock.unlock();
        }
    }

    // 使用写锁保护写操作
    public void write(int value) {
        writeLock.lock();
        try {
            // 模拟写入操作
            sharedData = value;
        } finally {
            writeLock.unlock();
        }
    }
    
    public static void main(String[] args) {
        ReadWriteLockDemo demo = new ReadWriteLockDemo();
        
        // 示例:一个线程进行写操作,其他线程进行读操作
        new Thread(() -> {
            demo.write(100);
            System.out.println("写线程修改数据为 100");
        }, "写线程").start();
        
        new Thread(() -> {
            int data = demo.read();
            System.out.println("读线程读取数据:" + data);
        }, "读线程1").start();
        
        new Thread(() -> {
            int data = demo.read();
            System.out.println("读线程读取数据:" + data);
        }, "读线程2").start();
    }
}

读锁和写锁之间的互斥关系

  • 读锁(共享锁)

    • 多个线程可以同时获取读锁,只要当前没有线程持有写锁。
    • 这意味着多个线程可以并发地执行读操作,提高了系统的并发性能。
  • 写锁(排他锁)

    • 写锁是互斥的,一次只允许一个线程获取写锁。
    • 当一个线程持有写锁时,其他线程无论是尝试获取读锁还是写锁都会被阻塞,直到写锁被释放,从而确保写操作的独占性。
  • 互斥规则

    • 如果某个线程正在持有写锁,那么所有试图获取读锁和写锁的线程都会阻塞。
    • 如果有线程持有读锁,那么试图获取写锁的线程将会等待所有读锁释放后才能获取写锁。这就是为什么在持有读锁的情况下不能直接升级为写锁(锁升级)——这可能导致死锁。
    • 然而,锁降级(从写锁降级为读锁)是允许的,即在持有写锁的情况下可以获取读锁,再释放写锁,保持对共享资源的访问权

补充:
读锁是共享的
多个线程可以同时持有读锁,只要没有线程持有写锁,这样可以允许并发读操作,从而提高系统并发性能。
“共享内存”指的是多个线程可以共享同一份数据的只读访问权限。

写锁是独占的
一次只有一个线程可以持有写锁,并且在写锁持有期间,其他线程无论是请求读锁还是写锁都会被阻塞。
“独占内存”则意味着写操作必须保证独占访问,防止数据出现并发修改问题。

  • 重入规则
    • 同一线程的写锁→读锁(可重入)
      当一个线程已经持有写锁时,它可以再次获取读锁。这种情况称为锁降级(从写锁降级到读锁),允许线程在完成写操作后继续进行读操作,而不需要释放写锁后再重新获得读锁。
    • 同一线程的读锁→写锁(不可重入)
      如果一个线程已经持有读锁,然后尝试获取写锁。ReentrantReadWriteLock 不支持从读锁升级为写锁,因为这样做很容易引发死锁(例如,其他线程同时持有读锁时,该线程就无法获得写锁)。

你可能感兴趣的:(Java并发编程,java,开发语言,jvm)