18.3.2 synchronized关键字实现原理

1. synchronized基础概念

1.1 synchronized的作用和特点

public class SynchronizedBasics {
    
    private int count = 0;
    private final Object lock = new Object();
    
    // 1. 修饰实例方法
    public synchronized void incrementInstance() {
        count++;
        System.out.println("实例方法同步,count = " + count);
    }
    
    // 2. 修饰静态方法
    public static synchronized void incrementStatic() {
        System.out.println("静态方法同步");
    }
    
    // 3. 修饰代码块 - 实例对象锁
    public void incrementBlock() {
        synchronized (this) {
            count++;
            System.out.println("实例对象锁,count = " + count);
        }
    }
    
    // 4. 修饰代码块 - 类锁
    public void incrementClassLock() {
        synchronized (SynchronizedBasics.class) {
            System.out.println("类锁同步");
        }
    }
    
    // 5. 修饰代码块 - 自定义锁
    public void incrementCustomLock() {
        synchronized (lock) {
            count++;
            System.out.println("自定义锁,count = " + count);
        }
    }
}

1.2 synchronized锁的分类

实例方法锁

this对象

当前实例的所有synchronized实例方法

synchronized void method()

静态方法锁

Class对象

当前类的所有synchronized静态方法

static synchronized void method()

实例对象锁

指定对象

使用同一对象的synchronized块

synchronized(this)

类锁

Class对象

使用同一Class对象的synchronized块

synchronized(Class.class)

自定义锁

自定义对象

使用同一自定义对象的synchronized块

synchronized(lock)

2. synchronized底层实现原理

2.1 字节码层面的实现

public class SynchronizedBytecode {
    
    private int value = 0;
    
    // 同步方法的字节码实现
    public synchronized void syncMethod() {
        value++;
    }
    
    // 同步代码块的字节码实现
    public void syncBlock() {
        synchronized (this) {
            value++;
        }
    }
    
    /*
     * 字节码分析:
     * 
     * 同步方法:
     * - 方法访问标志包含ACC_SYNCHRONIZED
     * - JVM通过检查方法访问标志来实现同步
     * 
     * 同步代码块:
     * - 使用monitorenter指令进入同步块
     * - 使用monitorexit指令退出同步块
     * - 编译器会确保每个monitorenter都有对应的monitorexit
     */
}

2.2 Monitor机制详解

public class MonitorMechanism {
    
    private final Object monitor = new Object();
    private int sharedResource = 0;
    
    /*
     * Monitor(监视器)是synchronized的核心实现机制
     * 
     * Monitor结构:
     * - Owner: 当前持有锁的线程
     * - EntryList: 等待获取锁的线程队列
     * - WaitSet: 调用wait()方法等待的线程集合
     * - Count: 重入计数器
     */
    
    public void demonstrateMonitorMechanism() {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        
        for (int i = 0; i < 10; i++) {
            final int threadId = i;
            executor.submit(() -> {
                acquireMonitor(threadId);
            });
        }
        
        executor.shutdown();
    }
    
    private void acquireMonitor(int threadId) {
        synchronized (monitor) {
            System.out.println("线程" + threadId + "获得monitor,开始执行");
            
            try {
                Thread.sleep(100);
                sharedResource++;
                System.out.println("线程" + threadId + "处理完毕,sharedResource = " + sharedResource);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            
            System.out.println("线程" + threadId + "释放monitor");
        }
    }
    
    // 演示wait/notify机制
    public void demonstrateWaitNotify() {
        final Object waitMonitor = new Object();
        
        // 等待线程
        Thread waiterThread = new Thread(() -> {
            synchronized (waitMonitor) {
                try {
                    System.out.println("等待线程进入WaitSet");
                    waitMonitor.wait(); // 进入WaitSet,释放monitor
                    System.out.println("等待线程被唤醒,重新获得monitor");
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        
        // 通知线程
        Thread notifierThread = new Thread(() -> {
            try {
                Thread.sleep(2000);
                synchronized (waitMonitor) {
                    System.out.println("通知线程获得monitor,准备唤醒等待线程");
                    waitMonitor.notify();
                    System.out.println("通知线程发出notify信号");
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        waiterThread.start();
        notifierThread.start();
    }
}

3. synchronized锁优化机制

3.1 JVM锁优化策略

public class SynchronizedOptimization {
    
    private int counter = 0;
    
    /*
     * JVM对synchronized的优化:
     * 1. 偏向锁(Biased Locking)
     * 2. 轻量级锁(Lightweight Locking)
     * 3. 重量级锁(Heavyweight Locking)
     * 4. 锁消除(Lock Elimination)
     * 5. 锁粗化(Lock Coarsening)
     */
    
    // 演示偏向锁
    public void demonstrateBiasedLock() {
        System.out.println("=== 偏向锁演示 ===");
        
        // 单线程环境下,synchronized会优化为偏向锁
        for (int i = 0; i < 1000000; i++) {
            synchronized (this) {
                counter++; // 偏向锁:记录线程ID,无需CAS操作
            }
        }
        
        System.out.println("偏向锁执行完毕,counter = " + counter);
    }
    
    // 演示轻量级锁
    public void demonstrateLightweightLock() {
        System.out.println("=== 轻量级锁演示 ===");
        
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 500000; i++) {
                synchronized (this) {
                    counter++; // 轻量级锁:使用CAS操作
                }
            }
        });
        
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 500000; i++) {
                synchronized (this) {
                    counter++; // 当有竞争时,偏向锁升级为轻量级锁
                }
            }
        });
        
        thread1.start();
        thread2.start();
        
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        System.out.println("轻量级锁执行完毕,counter = " + counter);
    }
    
    // 演示锁消除
    public void demonstrateLockElimination() {
        System.out.println("=== 锁消除演示 ===");
        
        // JVM会检测到这个锁没有逃逸到方法外部,会消除这个锁
        for (int i

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java面试圣经 文章被收录于专栏

Java面试圣经,带你练透java圣经

全部评论

相关推荐

08-15 13:50
门头沟学院 Java
点赞 评论 收藏
分享
猫头夜鹰:有没有一种可能,bg双九,有大厂实习的人数总和远远超过了hc总和
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务