轻量级锁案例

wen java案例 1

本文目录导读:

轻量级锁案例

  1. 轻量级锁概述
  2. 具体代码案例
  3. 性能对比测试
  4. 核心要点总结
  5. 最佳实践建议
  6. 监控和调试

我来为你详细讲解轻量级锁(Lightweight Lock)的案例。

轻量级锁概述

轻量级锁是Java SE 1.6中引入的锁优化机制,用于在没有多线程竞争或竞争不激烈的情况下,减少传统重量级锁(synchronized)使用操作系统互斥量产生的性能消耗。

轻量级锁的工作流程:

graph TD
    A[线程执行同步代码块] --> B{检查Mark Word}
    B -->|无锁状态| C[复制Mark Word到锁记录]
    B -->|已持有锁| D[重入计数]
    C --> E[CAS尝试将Mark Word替换为指向锁记录的指针]
    E -->|成功| F[获取轻量级锁成功]
    E -->|失败| G{Escape分析检查}
    F --> H[执行代码块]
    G -->|无竞争| I[膨胀为重量级锁]
    G -->|有竞争| J[进入阻塞状态]
    H --> K[执行完毕释放锁]
    K --> L[CAS恢复Mark Word]
    L -->|成功| M[锁释放完成]
    L -->|失败| N[唤醒等待线程]

具体代码案例

案例1:基础轻量级锁使用

public class LightweightLockExample {
    private int count = 0;
    // 使用synchronized关键字(默认优先使用轻量级锁)
    public synchronized void increment() {
        count++;
    }
    public static void main(String[] args) throws InterruptedException {
        LightweightLockExample example = new LightweightLockExample();
        // 单线程访问时,会使用轻量级锁
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            example.increment();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("单线程执行时间: " + (endTime - startTime) + "ms");
        System.out.println("最终count值: " + example.count);
    }
}

案例2:无竞争场景演示

public class NoContentionExample {
    private int value = 0;
    public void updateValue(int newValue) {
        synchronized (this) {  // 轻量级锁场景
            value = newValue;
            // 模拟短暂操作
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
    public static void main(String[] args) {
        NoContentionExample example = new NoContentionExample();
        // 单线程连续操作,没有竞争,适合轻量级锁
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100; i++) {
            example.updateValue(i);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("无竞争场景执行时间: " + (endTime - startTime) + "ms");
    }
}

案例3:锁重入场景

public class LockReentrancyExample {
    private StringBuilder sb = new StringBuilder();
    // 模拟锁重入
    public synchronized void append(String text) {
        sb.append(text);
        appendMore();  // 再次获取同一把锁(重入)
    }
    private synchronized void appendMore() {
        sb.append("!");
    }
    public static void main(String[] args) {
        LockReentrancyExample example = new LockReentrancyExample();
        // 单线程调用,轻量级锁支持重入
        example.append("Hello");
        System.out.println("重入结果: " + example.sb.toString());
        // 批量操作
        example.sb.setLength(0);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            example.append("test");
            example.sb.setLength(0);
        }
        long end = System.currentTimeMillis();
        System.out.println("重入操作耗时: " + (end - start) + "ms");
    }
}

案例4:膨胀为重量级锁的场景

public class LockInflationExample {
    private int sharedData = 0;
    private static final int THREAD_COUNT = 5;
    // 多线程竞争时,会从轻量级锁膨胀为重量级锁
    public void modifySharedData() {
        synchronized (this) {  // 竞争激烈时膨胀
            sharedData++;
            try {
                Thread.sleep(50);  // 增加持锁时间
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        LockInflationExample example = new LockInflationExample();
        // 创建多个线程竞争锁
        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 10; j++) {
                    example.modifySharedData();
                }
            });
            threads[i].start();
        }
        // 等待所有线程完成
        for (Thread thread : threads) {
            thread.join();
        }
        // 查看锁膨胀后的性能影响
        System.out.println("多线程竞争完成,最终值: " + example.sharedData);
    }
}

案例5:偏向锁到轻量级锁的升级

public class BiasToLightweightExample {
    private static class LockObject {
        int data = 0;
    }
    public static void main(String[] args) throws InterruptedException {
        LockObject lock = new LockObject();
        // 阶段1:单一线程获取锁(可能使用偏向锁)
        long start1 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            synchronized (lock) {
                lock.data++;
            }
        }
        long end1 = System.currentTimeMillis();
        System.out.println("单线程阶段耗时: " + (end1 - start1) + "ms");
        // 阶段2:另一个线程开始访问(可能升级为轻量级锁)
        Thread otherThread = new Thread(() -> {
            long start2 = System.currentTimeMillis();
            for (int i = 0; i < 100000; i++) {
                synchronized (lock) {
                    lock.data++;
                }
            }
            long end2 = System.currentTimeMillis();
            System.out.println("第二线程阶段耗时: " + (end2 - start2) + "ms");
        });
        otherThread.start();
        otherThread.join();
        System.out.println("最终data值: " + lock.data);
    }
}

性能对比测试

public class LockPerformanceTest {
    private int count = 0;
    // 使用synchronized(轻量级锁)
    public synchronized void syncIncrement() {
        count++;
    }
    // 使用Lock(需要处理)
    public void lockIncrement() {
        count++;
    }
    public static void main(String[] args) throws InterruptedException {
        LockPerformanceTest test = new LockPerformanceTest();
        // 单线程测试
        long start1 = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            test.syncIncrement();
        }
        long end1 = System.nanoTime();
        System.out.println("单线程synchronized耗时: " 
            + (end1 - start1) / 1_000_000 + "ms");
        // 多线程测试
        int threadCount = 4;
        Thread[] threads = new Thread[threadCount];
        long start2 = System.nanoTime();
        for (int i = 0; i < threadCount; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 250000; j++) {
                    test.syncIncrement();
                }
            });
            threads[i].start();
        }
        for (Thread thread : threads) {
            thread.join();
        }
        long end2 = System.nanoTime();
        System.out.println("多线程synchronized耗时: " 
            + (end2 - start2) / 1_000_000 + "ms");
    }
}

核心要点总结

特性 说明
适用场景 多线程交替执行,竞争不激烈
实现方式 CAS操作 + Mark Word复制
优点 避免操作系统互斥量开销,响应快速
缺点 竞争激烈时膨胀为重量级锁
升级条件 CAS失败且存在竞争
JVM参数 -XX:+UseSpinning 等

最佳实践建议

public class BestPracticeExample {
    private volatile int version = 0;
    // 使用局部变量减少锁竞争
    public void bestPractice() {
        int localCount = 0;
        synchronized (this) {
            localCount = version;
            // 短时间操作
            localCount++;
            version = localCount;
        }
    }
    // 使用Lock替代synchronized(显式控制)
    private final java.util.concurrent.locks.ReentrantLock lock = 
        new java.util.concurrent.locks.ReentrantLock();
    public void explicitLock() {
        lock.lock();
        try {
            // 业务逻辑
        } finally {
            lock.unlock();
        }
    }
}

监控和调试

可以通过JVM参数查看锁状态:

# 打印锁信息
-XX:+PrintLockInflation
# 偏向锁设置
-XX:+UseBiasedLocking
-XX:BiasedLockingStartupDelay=0

轻量级锁是JVM对synchronized的重要优化,理解其工作原理有助于编写高性能的并发代码,在竞争不激烈时性能非常好,竞争激烈时JVM会自动升级策略。

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