Java读写锁案例

wen java案例 2

本文目录导读:

Java读写锁案例

  1. 基础案例:缓存示例
  2. 读写锁降级示例
  3. 公平与非公平模式对比
  4. 实际业务场景:订单服务
  5. 读锁重入示例

我来给你一个完整的Java读写锁(ReentrantReadWriteLock)案例,包含详细注释和易用场景。

基础案例:缓存示例

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
 * 使用读写锁实现的缓存系统
 * 特点:读读不互斥、读写互斥、写写互斥
 */
public class ReadWriteLockCache<K, V> {
    private final Map<K, V> cache = new HashMap<>();
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    // 写入数据(独占锁)
    public void put(K key, V value) {
        lock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 正在写入: " + key + "=" + value);
            Thread.sleep(100); // 模拟耗时操作
            cache.put(key, value);
            System.out.println(Thread.currentThread().getName() + " 写入完成");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.writeLock().unlock();
        }
    }
    // 读取数据(共享锁)
    public V get(K key) {
        lock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 正在读取: " + key);
            Thread.sleep(100); // 模拟耗时操作
            V value = cache.get(key);
            System.out.println(Thread.currentThread().getName() + " 读取完成: " + value);
            return value;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return null;
        } finally {
            lock.readLock().unlock();
        }
    }
    // 测试代码
    public static void main(String[] args) {
        ReadWriteLockCache<String, String> cache = new ReadWriteLockCache<>();
        // 多个写线程
        for (int i = 0; i < 3; i++) {
            final int index = i;
            new Thread(() -> {
                cache.put("key" + index, "value" + index);
            }, "写线程-" + i).start();
        }
        // 多个读线程
        for (int i = 0; i < 5; i++) {
            final int index = i;
            new Thread(() -> {
                cache.get("key" + index);
            }, "读线程-" + i).start();
        }
    }
}

读写锁降级示例

import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
 * 演示锁降级:写锁 -> 读锁
 * 锁降级是指将写锁降级为读锁
 */
public class LockDowngradeDemo {
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private int data = 0;
    private boolean updated = false;
    /**
     * 锁降级的正确使用:
     * 1. 获取写锁
     * 2. 获取读锁
     * 3. 释放写锁
     * 4. 释放读锁
     */
    public void processData() {
        rwLock.readLock().lock();
        if (!updated) {
            // 必须释放读锁才能获取写锁(锁升级不允许)
            rwLock.readLock().unlock();
            // 获取写锁
            rwLock.writeLock().lock();
            try {
                // 再次检查状态(双重检查模式)
                if (!updated) {
                    data = (int) (Math.random() * 100);
                    System.out.println(Thread.currentThread().getName() 
                            + " 更新数据为: " + data);
                    updated = true;
                }
                // 锁降级:在持有写锁的情况下获取读锁
                rwLock.readLock().lock();
            } finally {
                // 释放写锁
                rwLock.writeLock().unlock();
            }
        }
        try {
            // 此时持有读锁,可以安全读取
            System.out.println(Thread.currentThread().getName() 
                    + " 读取数据: " + data);
        } finally {
            // 释放读锁
            rwLock.readLock().unlock();
        }
    }
    public static void main(String[] args) {
        LockDowngradeDemo demo = new LockDowngradeDemo();
        // 多个线程同时处理数据
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                demo.processData();
            }, "线程-" + i).start();
        }
    }
}

公平与非公平模式对比

import java.util.concurrent.locks.ReentrantReadWriteLock;
public class FairnessDemo {
    public static void testFairness(boolean fair) {
        ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
        System.out.println("\n" + (fair ? "=== 公平模式 ===" : "=== 非公平模式 ==="));
        // 创建多个写线程
        Runnable writeTask = () -> {
            lock.writeLock().lock();
            try {
                System.out.println(Thread.currentThread().getName() + " 获取写锁");
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.out.println(Thread.currentThread().getName() + " 释放写锁");
                lock.writeLock().unlock();
            }
        };
        // 创建多个读线程
        Runnable readTask = () -> {
            lock.readLock().lock();
            try {
                System.out.println(Thread.currentThread().getName() + " 获取读锁");
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.out.println(Thread.currentThread().getName() + " 释放读锁");
                lock.readLock().unlock();
            }
        };
        // 启动线程
        Thread[] threads = new Thread[8];
        for (int i = 0; i < 4; i++) {
            threads[i * 2] = new Thread(readTask, "读线程-" + i);
            threads[i * 2 + 1] = new Thread(writeTask, "写线程-" + i);
        }
        for (Thread t : threads) {
            t.start();
        }
        // 等待所有线程完成
        for (Thread t : threads) {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        // 测试公平模式
        testFairness(true);
        // 测试非公平模式
        testFairness(false);
    }
}

实际业务场景:订单服务

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
 * 订单服务:演示读写锁在真实业务中的应用
 */
public class OrderService {
    // 订单数据库模拟
    private static class Order {
        String orderId;
        String status;
        double amount;
        Order(String orderId, String status, double amount) {
            this.orderId = orderId;
            this.status = status;
            this.amount = amount;
        }
        @Override
        public String toString() {
            return String.format("Order{id='%s', status='%s', amount=%.2f}", 
                    orderId, status, amount);
        }
    }
    private final Map<String, Order> orderDB = new HashMap<>();
    private final ReadWriteLock lock = new ReentrantReadWriteLock(true); // 公平锁
    public OrderService() {
        // 初始化一些订单
        for (int i = 1; i <= 5; i++) {
            orderDB.put("ORD" + i, new Order("ORD" + i, "已创建", 100.00 * i));
        }
    }
    // 查询订单(读操作)
    public Order getOrder(String orderId) {
        lock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() 
                    + " 查询订单 " + orderId);
            Thread.sleep(100);
            return orderDB.get(orderId);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return null;
        } finally {
            lock.readLock().unlock();
        }
    }
    // 更新订单状态(写操作)
    public boolean updateOrderStatus(String orderId, String newStatus) {
        lock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() 
                    + " 更新订单 " + orderId + " 状态为: " + newStatus);
            Order order = orderDB.get(orderId);
            if (order == null) {
                return false;
            }
            Thread.sleep(200); // 模拟数据库更新操作
            order.status = newStatus;
            System.out.println(Thread.currentThread().getName() 
                    + " 订单更新成功");
            return true;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        } finally {
            lock.writeLock().unlock();
        }
    }
    // 批量查询(读操作)
    public void batchQuery() {
        lock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 开始批量查询");
            orderDB.entrySet().stream()
                    .limit(3)
                    .forEach(e -> System.out.println("  " + e.getValue()));
            Thread.sleep(200);
            System.out.println(Thread.currentThread().getName() + " 批量查询完成");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.readLock().unlock();
        }
    }
    public static void main(String[] args) {
        OrderService service = new OrderService();
        // 模拟订单处理场景
        System.out.println("=== 订单处理系统启动 ===\n");
        // 多个查询线程(读)
        for (int i = 0; i < 4; i++) {
            new Thread(() -> {
                service.getOrder("ORD" + (1 + (int)(Math.random() * 5)));
                service.batchQuery();
            }, "查询线程-" + i).start();
        }
        // 多个更新线程(写)
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                service.updateOrderStatus("ORD" + (1 + (int)(Math.random() * 5)), 
                        "已支付");
            }, "更新线程-" + i).start();
        }
    }
}

读锁重入示例

import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
 * 展示读写锁的重入特性
 */
public class LockReentrantDemo {
    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    public void readReentrant() {
        rwl.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() 
                    + " 第一次获取读锁");
            // 读锁可以重入
            rwl.readLock().lock();
            try {
                System.out.println(Thread.currentThread().getName() 
                        + " 第二次获取读锁(重入)");
            } finally {
                rwl.readLock().unlock();
                System.out.println(Thread.currentThread().getName() 
                        + " 释放第二次读锁");
            }
        } finally {
            rwl.readLock().unlock();
            System.out.println(Thread.currentThread().getName() 
                    + " 释放第一次读锁");
        }
    }
    public static void main(String[] args) {
        LockReentrantDemo demo = new LockReentrantDemo();
        // 多个线程测试读锁重入
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                demo.readReentrant();
            }, "线程-" + i).start();
        }
    }
}
  1. 锁特性

    • readLock():共享锁,允许多个线程同时读
    • writeLock():独占锁,写时不允许读和写
  2. 锁降级

    • 写锁可以降级为读锁(持有写锁时获取读锁)
    • 读锁不能升级为写锁(否则会死锁)
  3. 性能考量

    • 读多写少的场景使用读写锁性能较好
    • 读少写多时,考虑普通锁或更高级的锁
  4. 注意事项

    • 读写锁非公平模式下,可防止写线程饿死
    • 公平模式下,线程按请求顺序获取锁
    • 释放锁时要放在finally块中
  5. 使用场景

    • 缓存系统
    • 配置管理
    • 订单系统
    • 数据库连接池
    • 任何读多写少的并发场景

这些示例涵盖了读写锁的主要使用场景和特性,你可以根据实际需求调整和使用。

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