Bootstrap

Java并发编程 - JUC锁(独占共享锁/读写锁、ReentrantReadWriteLock、LockSupport)

Java 并发编程中的 java.util.concurrent(简称 JUC)包提供了多种高级并发工具,其中包括独占共享锁(读写锁)和 ReentrantReadWriteLock 等类。下面将详细介绍这些概念。

独占共享锁(Read-Write Locks)

独占共享锁也称为读写锁,它允许多个读操作同时进行,但只允许一个写操作进行。读写锁非常适合那些读操作远多于写操作的场景,因为在读写锁中,读操作可以并发执行,从而显著提高程序的性能。

读写锁的特点
  • 读-读共享:多个读线程可以同时访问共享资源。
  • 读-写互斥:读操作和写操作不能同时进行。
  • 写-写互斥:多个写操作也不能同时进行。

ReentrantReadWriteLock

ReentrantReadWriteLock 是 JUC 包中提供的一个实现了读写锁的类。它支持重入,即一个已经拥有读锁或写锁的线程可以再次获取同一个锁。

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

public class ReadWriteLockExample {
    private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
    private final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
    private String data;

    public void readData() {
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " is reading data: " + data);
        } finally {
            readLock.unlock();
        }
    }

    public void writeData(String newData) {
        writeLock.lock();
        try {
            data = newData;
            System.out.println(Thread.currentThread().getName() + " has written data: " + data);
        } finally {
            writeLock.unlock();
        }
    }
}

在这个示例中,我们创建了一个 ReentrantReadWriteLock 实例,并从中获取了读锁和写锁。readData 方法用于读取数据,而 writeData 方法用于写入数据。

LockSupport

LockSupportjava.util.concurrent.locks 包中的一个类,它提供了一组工具方法来支持高级的线程阻塞和唤醒操作。LockSupport 的核心功能在于它提供了一种机制,使得一个线程能够阻塞另一个线程,而不需要显式地获取和释放锁。

LockSupport 的主要方法
  • park():使当前线程进入等待状态,直到被另一个线程唤醒。
  • unpark(Thread thread):唤醒一个被 park 的线程。
  • parkNanos(long nanos):使当前线程进入等待状态,直到被另一个线程唤醒或等待了指定的纳秒时间。
  • parkUntil(long deadlineTime):使当前线程进入等待状态,直到被另一个线程唤醒或到达指定的截止时间。
示例
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

public class LockSupportExample {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("Thread T1 is waiting to be unparked...");
            LockSupport.park();
            System.out.println("Thread T1 has been unparked.");
        }, "T1");

        t1.start();
        TimeUnit.SECONDS.sleep(1); // 等待一段时间

        // 唤醒线程 T1
        LockSupport.unpark(t1);
    }
}

在这个示例中,线程 T1 使用 LockSupport.park() 进入等待状态,然后主线程使用 LockSupport.unpark(t1) 来唤醒 T1

总结

ReentrantReadWriteLockLockSupport 是 Java 并发编程中非常有用的工具。ReentrantReadWriteLock 提供了一种灵活的方式来实现读写锁,可以提高多线程程序的并发性能。而 LockSupport 则提供了一种简单的线程阻塞和唤醒机制,可以在不需要显式锁的情况下实现线程间的协作。

在实际开发中,选择使用这些工具取决于具体的应用场景。如果需要实现更高级别的锁机制或者更细粒度的线程控制,ReentrantReadWriteLockLockSupport 都是非常好的选择。

;