ReentrantReadWriteLock案例

wen java案例 2

本文目录导读:

ReentrantReadWriteLock案例

  1. 基础缓存案例
  2. 可降级的锁示例
  3. 读写锁计数器
  4. 读写锁 vs 普通锁性能对比
  5. 重要注意事项

我来为你提供几个ReentrantReadWriteLock的实用案例,从基础到进阶。

基础缓存案例

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockCache<K, V> {
    private final Map<K, V> cache = new HashMap<>();
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    // 写入操作 - 使用写锁
    public void put(K key, V value) {
        rwLock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 正在写入数据...");
            Thread.sleep(100); // 模拟耗时操作
            cache.put(key, value);
            System.out.println(Thread.currentThread().getName() + " 写入完成");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwLock.writeLock().unlock();
        }
    }
    // 读取操作 - 使用读锁(可并发)
    public V get(K key) {
        rwLock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 正在读取数据...");
            Thread.sleep(50);
            V value = cache.get(key);
            System.out.println(Thread.currentThread().getName() + " 读取完成: " + value);
            return value;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return null;
        } finally {
            rwLock.readLock().unlock();
        }
    }
    // 清空缓存
    public void clear() {
        rwLock.writeLock().lock();
        try {
            cache.clear();
        } finally {
            rwLock.writeLock().unlock();
        }
    }
    // 测试代码
    public static void main(String[] args) {
        ReadWriteLockCache<String, String> cache = new ReadWriteLockCache<>();
        cache.put("key1", "value1");
        cache.put("key2", "value2");
        // 模拟多个线程读取
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                cache.get("key1");
                cache.get("key2");
            }, "Reader-" + i).start();
        }
        // 模拟写入线程
        new Thread(() -> {
            cache.put("key3", "value3");
        }, "Writer").start();
    }
}

可降级的锁示例

import java.util.concurrent.locks.ReentrantReadWriteLock;
public class LockDowngradeExample {
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private volatile boolean dataReady = false;
    private Object data = null;
    // 写锁降级为读锁
    public void processData() {
        rwLock.writeLock().lock();
        try {
            // 1. 获取写锁,修改数据
            System.out.println(Thread.currentThread().getName() + " 获取写锁,更新数据");
            data = new Object();
            dataReady = true;
            // 2. 写锁降级为读锁
            rwLock.readLock().lock();
            System.out.println(Thread.currentThread().getName() + " 写锁降级为读锁");
        } finally {
            rwLock.writeLock().unlock(); // 释放写锁,仍持有读锁
        }
        try {
            // 3. 此时持有读锁,可以继续读取数据
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + " 持有读锁,读取数据: " + data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwLock.readLock().unlock(); // 释放读锁
        }
    }
    // 错误的降级方式(不推荐)
    public void wrongProcessData() {
        rwLock.readLock().lock();
        try {
            // 读锁不能升级为写锁,会导致死锁
            rwLock.writeLock().lock(); // 这里会导致死锁
            try {
                data = new Object();
            } finally {
                rwLock.writeLock().unlock();
            }
        } finally {
            rwLock.readLock().unlock();
        }
    }
    public static void main(String[] args) {
        LockDowngradeExample example = new LockDowngradeExample();
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                example.processData();
            }, "Thread-" + i).start();
        }
    }
}

读写锁计数器

import java.util.concurrent.locks.ReentrantReadWriteLock;
public class CounterWithReadWriteLock {
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private int count = 0;
    private final long startTime = System.currentTimeMillis();
    // 读取计数
    public int getCount() {
        rwLock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 读取计数: " + count);
            return count;
        } finally {
            rwLock.readLock().unlock();
        }
    }
    // 增加计数
    public void increment() {
        rwLock.writeLock().lock();
        try {
            count++;
            System.out.println(Thread.currentThread().getName() + " 增加计数到: " + count);
        } finally {
            rwLock.writeLock().unlock();
        }
    }
    // 获取运行时间
    public long getElapsedTime() {
        return System.currentTimeMillis() - startTime;
    }
    public static void main(String[] args) throws InterruptedException {
        CounterWithReadWriteLock counter = new CounterWithReadWriteLock();
        // 创建多个读取线程
        Thread[] readers = new Thread[5];
        for (int i = 0; i < readers.length; i++) {
            readers[i] = new Thread(() -> {
                for (int j = 0; j < 100; j++) {
                    counter.getCount();
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "Reader-" + i);
        }
        // 创建写入线程
        Thread writer = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                counter.increment();
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Writer");
        // 启动所有线程
        for (Thread reader : readers) {
            reader.start();
        }
        writer.start();
        // 等待完成
        for (Thread reader : readers) {
            reader.join();
        }
        writer.join();
        System.out.println("最终计数: " + counter.getCount());
        System.out.println("运行时间(毫秒): " + counter.getElapsedTime());
    }
}

读写锁 vs 普通锁性能对比

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class PerformanceComparison {
    private static class SharedData {
        private int value = 0;
        // 使用ReentrantLock
        public static void testWithReentrantLock(int readThreads, int writeThreads, int iterations) {
            Lock lock = new ReentrantLock();
            SharedData data = new SharedData();
            long start = System.currentTimeMillis();
            // 创建线程
            Thread[] threads = new Thread[readThreads + writeThreads];
            // 读取线程
            for (int i = 0; i < readThreads; i++) {
                threads[i] = new Thread(() -> {
                    for (int j = 0; j < iterations; j++) {
                        lock.lock();
                        try {
                            int v = data.value;
                        } finally {
                            lock.unlock();
                        }
                    }
                });
            }
            // 写入线程
            for (int i = 0; i < writeThreads; i++) {
                threads[readThreads + i] = new Thread(() -> {
                    for (int j = 0; j < iterations; j++) {
                        lock.lock();
                        try {
                            data.value++;
                        } finally {
                            lock.unlock();
                        }
                    }
                });
            }
            // 启动和等待
            for (Thread t : threads) t.start();
            for (Thread t : threads) {
                try { t.join(); } catch (InterruptedException e) {}
            }
            System.out.println("ReentrantLock 耗时: " + (System.currentTimeMillis() - start) + "ms");
        }
        // 使用ReentrantReadWriteLock
        public static void testWithReadWriteLock(int readThreads, int writeThreads, int iterations) {
            ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
            SharedData data = new SharedData();
            long start = System.currentTimeMillis();
            Thread[] threads = new Thread[readThreads + writeThreads];
            // 读取线程(使用读锁)
            for (int i = 0; i < readThreads; i++) {
                threads[i] = new Thread(() -> {
                    for (int j = 0; j < iterations; j++) {
                        rwLock.readLock().lock();
                        try {
                            int v = data.value;
                        } finally {
                            rwLock.readLock().unlock();
                        }
                    }
                });
            }
            // 写入线程(使用写锁)
            for (int i = 0; i < writeThreads; i++) {
                threads[readThreads + i] = new Thread(() -> {
                    for (int j = 0; j < iterations; j++) {
                        rwLock.writeLock().lock();
                        try {
                            data.value++;
                        } finally {
                            rwLock.writeLock().unlock();
                        }
                    }
                });
            }
            for (Thread t : threads) t.start();
            for (Thread t : threads) {
                try { t.join(); } catch (InterruptedException e) {}
            }
            System.out.println("ReentrantReadWriteLock 耗时: " + (System.currentTimeMillis() - start) + "ms");
        }
    }
    public static void main(String[] args) {
        System.out.println("=== 读多写少场景 ===");
        SharedData.testWithReentrantLock(8, 2, 10000);
        SharedData.testWithReadWriteLock(8, 2, 10000);
        System.out.println("\n=== 读写均衡场景 ===");
        SharedData.testWithReentrantLock(5, 5, 10000);
        SharedData.testWithReadWriteLock(5, 5, 10000);
    }
}

重要注意事项

public class ReadWriteLockImportantNotes {
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true); // 公平锁
    public void importantNotes() {
        // 1. 锁的公平性
        System.out.println("公平模式: " + rwLock.isFair());
        // 2. 锁的可重入性
        rwLock.writeLock().lock();
        try {
            System.out.println("写锁可重入,当前锁数量: " + rwLock.getWriteHoldCount());
            // 写锁内可以再次获取写锁
            rwLock.writeLock().lock();
            try {
                System.out.println("再次获取写锁,数量: " + rwLock.getWriteHoldCount());
            } finally {
                rwLock.writeLock().unlock();
            }
            // 写锁降级为读锁
            rwLock.readLock().lock();
            try {
                System.out.println("写锁已降级为读锁");
            } finally {
                rwLock.readLock().unlock();
            }
        } finally {
            rwLock.writeLock().unlock();
        }
        // 3. 查询锁状态
        System.out.println("是否有等待获取读锁的线程: " + rwLock.hasQueuedThreads());
        System.out.println("队列中等待的线程数: " + rwLock.getQueueLength());
    }
    public static void main(String[] args) {
        ReadWriteLockImportantNotes example = new ReadWriteLockImportantNotes();
        example.importantNotes();
        // 提醒:避免锁升级导致死锁
        System.out.println("\n警告:读锁升级为写锁会导致死锁,应该避免!");
    }
}
  1. 读写分离:读锁可多个线程共享,写锁独占
  2. 锁降级:写锁可以降级为读锁,但读锁不能升级为写锁
  3. 性能优势:在读多写少的场景下性能更好
  4. 公平性:可通过构造参数设置公平锁
  5. 可重入性:支持锁的重入,但要注意控制重入次数

选择建议:

  • 读多写少:使用ReentrantReadWriteLock
  • 写多读少:使用ReentrantLocksynchronized
  • 读写均衡:需要根据具体场景测试决定

抱歉,评论功能暂时关闭!