ReentrantLock案例

wen java案例 2

本文目录导读:

ReentrantLock案例

  1. 基础使用案例
  2. 公平锁与非公平锁对比
  3. 生产者-消费者案例
  4. 高级特性展示
  5. 实际业务场景案例:银行账户转账
  6. 注意事项

我将为您提供一个完整的ReentrantLock案例,展示其核心特性和典型使用场景。

基础使用案例

import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockBasicDemo {
    private final ReentrantLock lock = new ReentrantLock();
    private int count = 0;
    // 基本加锁/解锁
    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();  // 必须在finally中解锁
        }
    }
    // 可重入性演示
    public void reentrantDemo() {
        lock.lock();
        try {
            System.out.println("第一次获取锁");
            // 再次获取锁(可重入)
            lock.lock();
            try {
                System.out.println("第二次获取锁(可重入)");
                // 执行一些操作
            } finally {
                lock.unlock();
            }
        } finally {
            lock.unlock();
        }
    }
    // 尝试获取锁(非阻塞)
    public boolean tryIncrement() {
        if (lock.tryLock()) {
            try {
                count++;
                return true;
            } finally {
                lock.unlock();
            }
        }
        return false;
    }
    // 带超时的尝试获取锁
    public boolean tryIncrementWithTimeout(long timeout, TimeUnit unit) 
            throws InterruptedException {
        if (lock.tryLock(timeout, unit)) {
            try {
                count++;
                return true;
            } finally {
                lock.unlock();
            }
        }
        return false;
    }
    // 可中断的锁获取
    public void interruptibleLock() throws InterruptedException {
        lock.lockInterruptibly();  // 可中断获取锁
        try {
            // 执行操作
            Thread.sleep(100);
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) {
        ReentrantLockBasicDemo demo = new ReentrantLockBasicDemo();
        // 测试可重入性
        demo.reentrantDemo();
        // 测试基本功能
        System.out.println("Count: " + demo.count);
    }
}

公平锁与非公平锁对比

import java.util.concurrent.locks.ReentrantLock;
public class FairnessDemo {
    private final ReentrantLock fairLock = new ReentrantLock(true);    // 公平锁
    private final ReentrantLock unfairLock = new ReentrantLock(false); // 非公平锁
    public void testFairness(ReentrantLock lock, String lockName) {
        Runnable task = () -> {
            for (int i = 0; i < 3; i++) {
                lock.lock();
                try {
                    System.out.println(Thread.currentThread().getName() 
                        + " 获取" + lockName);
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    lock.unlock();
                }
            }
        };
        System.out.println("\n=== " + lockName + " 测试 ===");
        Thread[] threads = new Thread[5];
        for (int i = 0; i < 5; i++) {
            threads[i] = new Thread(task, "线程" + i);
        }
        for (Thread t : threads) {
            t.start();
        }
        try {
            for (Thread t : threads) {
                t.join();
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    public static void main(String[] args) {
        FairnessDemo demo = new FairnessDemo();
        demo.testFairness(demo.fairLock, "公平锁");
        demo.testFairness(demo.unfairLock, "非公平锁");
    }
}

生产者-消费者案例

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ProducerConsumerDemo {
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notEmpty = lock.newCondition();
    private final Condition notFull = lock.newCondition();
    private final Queue<Integer> queue = new LinkedList<>();
    private final int capacity = 5;
    private int value = 0;
    // 生产者
    public void produce() {
        lock.lock();
        try {
            // 队列已满时等待
            while (queue.size() == capacity) {
                System.out.println("队列已满,生产者等待...");
                notFull.await();
            }
            value++;
            queue.offer(value);
            System.out.println("生产者生产: " + value + ",队列大小: " + queue.size());
            // 唤醒消费者
            notEmpty.signal();
            Thread.sleep(100); // 模拟生产耗时
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
    // 消费者
    public void consume() {
        lock.lock();
        try {
            // 队列为空时等待
            while (queue.isEmpty()) {
                System.out.println("队列为空,消费者等待...");
                notEmpty.await();
            }
            Integer item = queue.poll();
            System.out.println("消费者消费: " + item + ",队列大小: " + queue.size());
            // 唤醒生产者
            notFull.signal();
            Thread.sleep(100); // 模拟消费耗时
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) {
        ProducerConsumerDemo demo = new ProducerConsumerDemo();
        // 启动生产者线程
        Thread producerThread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                demo.produce();
            }
        }, "生产者");
        // 启动消费者线程
        Thread consumerThread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                demo.consume();
            }
        }, "消费者");
        producerThread.start();
        consumerThread.start();
        try {
            producerThread.join();
            consumerThread.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("生产消费完成");
    }
}

高级特性展示

import java.util.concurrent.locks.ReentrantLock;
public class AdvancedReentrantLockDemo {
    private final ReentrantLock lock = new ReentrantLock();
    // 锁状态查询
    public void lockStateDemo() {
        System.out.println("=== 锁状态查询 ===");
        System.out.println("是否有线程持有锁: " + lock.isLocked());
        System.out.println("是否公平锁: " + lock.isFair());
        lock.lock();
        try {
            System.out.println("持有锁后: " + lock.isLocked());
            System.out.println("持有数: " + lock.getHoldCount());
            System.out.println("等待队列长度: " + lock.getQueueLength());
        } finally {
            lock.unlock();
        }
    }
    // 使用wait queue查询
    public void waitQueueDemo() {
        lock.lock();
        try {
            Thread t = new Thread(() -> {
                lock.lock();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    lock.unlock();
                }
            });
            t.start();
            Thread.sleep(100);
            System.out.println("=== 等待队列信息 ===");
            System.out.println("当前线程是否持有锁: " + lock.isHeldByCurrentThread());
            System.out.println("是否有线程在等待: " + lock.hasQueuedThreads());
            System.out.println("等待线程数: " + lock.getQueueLength());
            t.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
    // 性能对比:ReentrantLock vs synchronized
    public static void performanceTest() {
        int iterations = 100000;
        int threadCount = 10;
        // synchronized 测试
        Object syncLock = new Object();
        long startTime = System.nanoTime();
        Thread[] syncThreads = new Thread[threadCount];
        for (int i = 0; i < threadCount; i++) {
            syncThreads[i] = new Thread(() -> {
                for (int j = 0; j < iterations; j++) {
                    synchronized (syncLock) {
                        // 模拟操作
                    }
                }
            });
            syncThreads[i].start();
        }
        try {
            for (Thread t : syncThreads) t.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        long syncTime = System.nanoTime() - startTime;
        // ReentrantLock 测试
        ReentrantLock reentrantLock = new ReentrantLock();
        startTime = System.nanoTime();
        Thread[] lockThreads = new Thread[threadCount];
        for (int i = 0; i < threadCount; i++) {
            lockThreads[i] = new Thread(() -> {
                for (int j = 0; j < iterations; j++) {
                    reentrantLock.lock();
                    try {
                        // 模拟操作
                    } finally {
                        reentrantLock.unlock();
                    }
                }
            });
            lockThreads[i].start();
        }
        try {
            for (Thread t : lockThreads) t.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        long lockTime = System.nanoTime() - startTime;
        System.out.println("=== 性能对比 ===");
        System.out.println("Synchronized耗时: " + syncTime / 1_000_000 + "ms");
        System.out.println("ReentrantLock耗时: " + lockTime / 1_000_000 + "ms");
    }
    public static void main(String[] args) {
        AdvancedReentrantLockDemo demo = new AdvancedReentrantLockDemo();
        demo.lockStateDemo();
        demo.waitQueueDemo();
        performanceTest();
    }
}

实际业务场景案例:银行账户转账

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
public class BankAccountDemo {
    // 账户类
    static class Account {
        private final ReentrantLock lock = new ReentrantLock();
        private String accountId;
        private double balance;
        public Account(String accountId, double balance) {
            this.accountId = accountId;
            this.balance = balance;
        }
        public String getAccountId() {
            return accountId;
        }
        public double getBalance() {
            return balance;
        }
        public void debit(double amount) {  // 扣款
            balance -= amount;
        }
        public void credit(double amount) {  // 存款
            balance += amount;
        }
        public ReentrantLock getLock() {
            return lock;
        }
    }
    private final Map<String, Account> accounts = new HashMap<>();
    public BankAccountDemo() {
        // 初始化账户
        accounts.put("A001", new Account("A001", 5000));
        accounts.put("A002", new Account("A002", 3000));
        accounts.put("A003", new Account("A003", 8000));
    }
    // 安全转账(避免死锁)
    public boolean transfer(String fromId, String toId, double amount) {
        Account fromAccount = accounts.get(fromId);
        Account toAccount = accounts.get(toId);
        // 按账户ID排序获取锁,避免死锁
        Account firstLock;
        Account secondLock;
        if (fromId.compareTo(toId) < 0) {
            firstLock = fromAccount;
            secondLock = toAccount;
        } else {
            firstLock = toAccount;
            secondLock = fromAccount;
        }
        firstLock.getLock().lock();
        try {
            secondLock.getLock().lock();
            try {
                // 检查余额
                if (fromAccount.getBalance() >= amount) {
                    fromAccount.debit(amount);
                    toAccount.credit(amount);
                    System.out.println("转账成功: " + fromId + " -> " + toId 
                        + ",金额: " + amount);
                    System.out.println("  " + fromId + "余额: " + fromAccount.getBalance());
                    System.out.println("  " + toId + "余额: " + toAccount.getBalance());
                    return true;
                } else {
                    System.out.println("转账失败: " + fromId + "余额不足");
                    return false;
                }
            } finally {
                secondLock.getLock().unlock();
            }
        } finally {
            firstLock.getLock().unlock();
        }
    }
    public static void main(String[] args) {
        BankAccountDemo bank = new BankAccountDemo();
        // 模拟并发转账
        Thread t1 = new Thread(() -> {
            bank.transfer("A001", "A002", 1000);
        });
        Thread t2 = new Thread(() -> {
            bank.transfer("A002", "A003", 500);
        });
        Thread t3 = new Thread(() -> {
            bank.transfer("A003", "A001", 2000);
        });
        t1.start();
        t2.start();
        t3.start();
        try {
            t1.join();
            t2.join();
            t3.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("\n=== 最终账户状态 ===");
        Map<String, Account> finalAccounts = bank.accounts;
        for (Map.Entry<String, Account> entry : finalAccounts.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue().getBalance());
        }
    }
}
特性 说明 示例
可重入性 同一线程可以多次获取同一把锁 reentrantDemo()
可中断 获取锁时可以被中断 lockInterruptibly()
超时机制 尝试获取锁可设置超时时间 tryLock(timeout, unit)
公平性 可配置公平锁或非公平锁 new ReentrantLock(true)
多条件 支持多个Condition实现精细等待/通知 生产者-消费者案例
锁状态查询 可查询锁的状态和持有情况 isLocked(), getHoldCount()

注意事项

  1. 必须手动释放锁:在finally块中调用unlock()
  2. 避免死锁:多个锁时要保持一致的获取顺序
  3. 性能考虑:简单场景使用synchronized,复杂场景使用ReentrantLock
  4. 线程安全:确保所有访问共享资源的路径都使用锁保护

这些案例覆盖了ReentrantLock的主要特性和典型应用场景,您可以根据实际需求选择使用。

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