Java锁案例

wen java案例 2

本文目录导读:

Java锁案例

  1. synchronized 基础锁
  2. ReentrantLock 可重入锁
  3. 读写锁案例
  4. Condition 条件锁
  5. 高级锁案例
  6. 无锁编程案例
  7. 锁性能比较案例
  8. 最佳实践总结

我将为你全面介绍Java中的锁机制,包含各种锁的使用案例、实现原理和最佳实践。

synchronized 基础锁

同步方法案例

public class SynchronizedMethodExample {
    private int count = 0;
    // 同步实例方法
    public synchronized void increment() {
        count++;
    }
    // 同步静态方法
    public synchronized static void staticMethod() {
        System.out.println("静态同步方法");
    }
    // 使用示例
    public static void main(String[] args) throws InterruptedException {
        SynchronizedMethodExample example = new SynchronizedMethodExample();
        // 创建10个线程同时增加count
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    example.increment();
                }
            });
            threads[i].start();
        }
        // 等待所有线程完成
        for (Thread t : threads) {
            t.join();
        }
        System.out.println("最终count值: " + example.count);
    }
}

同步代码块案例

public class SynchronizedBlockExample {
    private final Object lock = new Object();
    private List<String> list = new ArrayList<>();
    public void addItem(String item) {
        // 使用专用的锁对象
        synchronized (lock) {
            list.add(item);
            System.out.println(Thread.currentThread().getName() + " 添加元素: " + item);
        }
    }
    public void removeItem(String item) {
        synchronized (lock) {
            if (list.contains(item)) {
                list.remove(item);
                System.out.println(Thread.currentThread().getName() + " 移除元素: " + item);
            }
        }
    }
    // 使用类对象作为锁
    public static void printClassInfo() {
        synchronized (SynchronizedBlockExample.class) {
            System.out.println("类级别的锁");
        }
    }
}

ReentrantLock 可重入锁

基本使用案例

import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
    private final ReentrantLock lock = new ReentrantLock();
    private int count = 0;
    public void increment() {
        lock.lock();
        try {
            count++;
            System.out.println(Thread.currentThread().getName() + " count: " + count);
            Thread.sleep(50);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();  // 确保解锁
        }
    }
    // 可重入示例
    public void outerMethod() {
        lock.lock();
        try {
            System.out.println("外部方法");
            innerMethod();  // 同一个线程可以再次获取锁
        } finally {
            lock.unlock();
        }
    }
    public void innerMethod() {
        lock.lock();
        try {
            System.out.println("内部方法");
        } finally {
            lock.unlock();
        }
    }
}

公平锁和超时锁案例

public class FairLockExample {
    // 公平锁:多个线程按照申请锁的顺序获得锁
    private final ReentrantLock fairLock = new ReentrantLock(true);
    // 非公平锁:不保证顺序
    private final ReentrantLock nonFairLock = new ReentrantLock(false);
    public void tryLockWithTimeout() {
        if (fairLock.tryLock()) {
            try {
                System.out.println("立即获取锁成功");
            } finally {
                fairLock.unlock();
            }
        }
    }
    public void tryLockDuration() {
        try {
            // 尝试在3秒内获取锁
            if (fairLock.tryLock(3, TimeUnit.SECONDS)) {
                try {
                    System.out.println("在3秒内获取到锁");
                } finally {
                    fairLock.unlock();
                }
            } else {
                System.out.println("3秒内未获取到锁");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

可中断锁案例

public class InterruptibleLockExample {
    private final ReentrantLock lock = new ReentrantLock();
    public void interruptibleLock() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + " 尝试获取锁");
        // lockInterruptibly() 允许在等待锁时被中断
        lock.lockInterruptibly();
        try {
            System.out.println(Thread.currentThread().getName() + " 获取到锁");
            Thread.sleep(5000);  // 模拟长时间工作
        } finally {
            lock.unlock();
            System.out.println(Thread.currentThread().getName() + " 释放锁");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        InterruptibleLockExample example = new InterruptibleLockExample();
        Thread t1 = new Thread(() -> {
            try {
                example.interruptibleLock();
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + " 被中断");
            }
        }, "线程1");
        Thread t2 = new Thread(() -> {
            try {
                example.interruptibleLock();
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + " 被中断");
            }
        }, "线程2");
        t1.start();
        Thread.sleep(100);
        t2.start();
        Thread.sleep(100);
        t2.interrupt();  // 中断等待中的线程2
    }
}

读写锁案例

ReentrantReadWriteLock

import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockExample {
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
    private final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
    private Map<String, String> cache = new HashMap<>();
    // 读操作 - 可并发执行
    public String get(String key) {
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 读取数据");
            Thread.sleep(100);
            return cache.get(key);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return null;
        } finally {
            readLock.unlock();
        }
    }
    // 写操作 - 独占执行
    public void put(String key, String value) {
        writeLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 写入数据");
            Thread.sleep(200);
            cache.put(key, value);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            writeLock.unlock();
        }
    }
    public static void main(String[] args) {
        ReadWriteLockExample example = new ReadWriteLockExample();
        // 多个读线程
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                for (int j = 0; j < 3; j++) {
                    example.get("key");
                }
            }, "读线程-" + i).start();
        }
        // 写线程
        new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                example.put("key", "value" + i);
            }
        }, "写线程").start();
    }
}

StampedLock(Java 8+)

import java.util.concurrent.locks.StampedLock;
public class StampedLockExample {
    private final StampedLock stampedLock = new StampedLock();
    private double x, y;
    // 独占写锁
    public void move(double deltaX, double deltaY) {
        long stamp = stampedLock.writeLock();
        try {
            x += deltaX;
            y += deltaY;
        } finally {
            stampedLock.unlockWrite(stamp);
        }
    }
    // 乐观读锁 - 允许其他线程写
    public double distanceFromOrigin() {
        long stamp = stampedLock.tryOptimisticRead();
        double currentX = x;
        double currentY = y;
        // 检查读取期间是否有写入
        if (!stampedLock.validate(stamp)) {
            // 有写入,升级为悲观读锁
            stamp = stampedLock.readLock();
            try {
                currentX = x;
                currentY = y;
            } finally {
                stampedLock.unlockRead(stamp);
            }
        }
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }
    // 悲观读锁
    public double readWithLock() {
        long stamp = stampedLock.readLock();
        try {
            return Math.sqrt(x * x + y * y);
        } finally {
            stampedLock.unlockRead(stamp);
        }
    }
}

Condition 条件锁

生产者消费者案例

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ProductConsumerExample {
    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 maxSize = 5;
    private int value = 0;
    // 生产者
    public void produce() {
        lock.lock();
        try {
            // 队列已满,等待消费
            while (queue.size() == maxSize) {
                System.out.println("队列已满,生产者等待...");
                notFull.await();
            }
            int producedValue = ++value;
            queue.add(producedValue);
            System.out.println("生产: " + producedValue + " 队列大小: " + queue.size());
            Thread.sleep(500);
            // 唤醒消费者
            notEmpty.signalAll();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
    // 消费者
    public void consume() {
        lock.lock();
        try {
            // 队列为空,等待生产
            while (queue.isEmpty()) {
                System.out.println("队列为空,消费者等待...");
                notEmpty.await();
            }
            int consumedValue = queue.poll();
            System.out.println("消费: " + consumedValue + " 队列大小: " + queue.size());
            Thread.sleep(1000);
            // 唤醒生产者
            notFull.signalAll();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) {
        ProductConsumerExample example = new ProductConsumerExample();
        // 2个生产者线程
        for (int i = 0; i < 2; i++) {
            new Thread(() -> {
                for (int j = 0; j < 10; j++) {
                    example.produce();
                }
            }, "生产者" + i).start();
        }
        // 3个消费者线程
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                for (int j = 0; j < 10; j++) {
                    example.consume();
                }
            }, "消费者" + i).start();
        }
    }
}

高级锁案例

Semaphore 信号量

import java.util.concurrent.Semaphore;
public class SemaphoreExample {
    // 最多允许3个线程同时访问
    private final Semaphore semaphore = new Semaphore(3);
    public void accessResource() {
        try {
            semaphore.acquire();
            System.out.println(Thread.currentThread().getName() + " 正在访问资源");
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + " 完成访问");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            semaphore.release();
        }
    }
    public static void main(String[] args) {
        SemaphoreExample example = new SemaphoreExample();
        for (int i = 0; i < 10; i++) {
            new Thread(example::accessResource, "线程" + i).start();
        }
    }
}

CountDownLatch 倒计时门闩

import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        int threadCount = 5;
        CountDownLatch latch = new CountDownLatch(threadCount);
        // 启动5个线程
        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            new Thread(() -> {
                try {
                    System.out.println("线程" + threadNum + " 开始执行");
                    Thread.sleep(2000);
                    System.out.println("线程" + threadNum + " 执行完成");
                    latch.countDown();  // 计数器减1
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
        }
        System.out.println("主线程等待所有子线程完成...");
        latch.await();  // 等待计数变为0
        System.out.println("所有线程已完成,主线程继续执行");
    }
}

CyclicBarrier 循环屏障

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
    private final CyclicBarrier barrier;
    private final int threadCount = 4;
    public CyclicBarrierExample() {
        // 当4个线程都到达屏障时,执行汇总任务
        barrier = new CyclicBarrier(threadCount, () -> {
            System.out.println("=== 所有线程已到达屏障,汇总开始 ===");
        });
    }
    public void processData() {
        try {
            System.out.println(Thread.currentThread().getName() + " 开始处理数据");
            Thread.sleep(1000 + (int)(Math.random() * 3000));
            System.out.println(Thread.currentThread().getName() + " 完成处理,等待其他线程");
            barrier.await();  // 等待其他线程
            System.out.println(Thread.currentThread().getName() + " 继续执行后续工作");
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        CyclicBarrierExample example = new CyclicBarrierExample();
        for (int i = 0; i < 4; i++) {
            new Thread(example::processData, "线程" + i).start();
        }
    }
}

无锁编程案例

Atomic 原子类

import java.util.concurrent.atomic.*;
public class AtomicExample {
    private final AtomicInteger count = new AtomicInteger(0);
    private final AtomicReference<String> reference = new AtomicReference<>("初始值");
    public void increment() {
        // CAS操作
        int oldValue = count.get();
        while (!count.compareAndSet(oldValue, oldValue + 1)) {
            oldValue = count.get();
        }
    }
    // 使用Lambda表达式
    public void safeIncrement() {
        count.updateAndGet(x -> x + 1);
    }
    public static void main(String[] args) throws InterruptedException {
        AtomicExample example = new AtomicExample();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    example.safeIncrement();
                }
            }).start();
        }
        Thread.sleep(2000);
        System.out.println("最终结果: " + example.count.get());
    }
}

锁性能比较案例

public class LockPerformanceComparison {
    private static final int THREAD_COUNT = 4;
    private static final int ITERATIONS = 1000000;
    // 测试synchronized
    public static void testSynchronized() throws InterruptedException {
        Object lock = new Object();
        long[] counts = {0};
        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i] = new Thread(() -> {
                long localCount = 0;
                for (int j = 0; j < ITERATIONS; j++) {
                    synchronized (lock) {
                        localCount++;
                    }
                }
                synchronized (lock) {
                    counts[0] += localCount;
                }
            });
            threads[i].start();
        }
        for (Thread t : threads) t.join();
        System.out.println("synchronized结果: " + counts[0]);
    }
    // 测试ReentrantLock
    public static void testReentrantLock() throws InterruptedException {
        ReentrantLock lock = new ReentrantLock();
        long[] counts = {0};
        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i] = new Thread(() -> {
                long localCount = 0;
                for (int j = 0; j < ITERATIONS; j++) {
                    lock.lock();
                    try {
                        localCount++;
                    } finally {
                        lock.unlock();
                    }
                }
                lock.lock();
                try {
                    counts[0] += localCount;
                } finally {
                    lock.unlock();
                }
            });
            threads[i].start();
        }
        for (Thread t : threads) t.join();
        System.out.println("ReentrantLock结果: " + counts[0]);
    }
    // 测试AtomicInteger
    public static void testAtomic() throws InterruptedException {
        AtomicInteger counter = new AtomicInteger(0);
        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < ITERATIONS; j++) {
                    counter.incrementAndGet();
                }
            });
            threads[i].start();
        }
        for (Thread t : threads) t.join();
        System.out.println("AtomicInteger结果: " + counter.get());
    }
}

最佳实践总结

锁选择指南

public class LockSelectionGuide {
    /*
     * 选择建议:
     * 1. 简单同步:使用 synchronized
     * 2. 需要高级特性(可中断、超时、公平性):使用 ReentrantLock
     * 3. 读多写少:使用 ReadWriteLock 或 StampedLock
     * 4. 计数器:使用 Atomic 类
     * 5. 线程间协作:使用 Condition
     * 6. 访问控制:使用 Semaphore
     */
}

锁优化技巧

public class LockOptimizationTips {
    // 1. 缩小锁范围
    private int count = 0;
    public synchronized void badMethod() {
        System.out.println("无关操作");
        count++;
        System.out.println("更多无关操作");
    }
    public void goodMethod() {
        System.out.println("无关操作");
        synchronized (this) {
            count++;
        }
        System.out.println("更多无关操作");
    }
}

Java提供了多种锁机制,选择时需要根据具体场景:

  • synchronized:简单可靠,适合大多数同步需求
  • ReentrantLock:功能强大,支持中断、超时、公平锁
  • ReadWriteLock/StampedLock:优化读多写少场景
  • Atomic:无锁操作,适合简单计数器
  • Semaphore/CyclicBarrier/CountDownLatch:线程协作工具

记住三个原则:

  1. 尽量缩小锁的范围
  2. 避免死锁(按固定顺序获取锁)
  3. 使用try-finally确保锁一定会释放

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