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实例方法 |
|
静态方法锁 |
Class对象 |
当前类的所有synchronized静态方法 |
|
实例对象锁 |
指定对象 |
使用同一对象的synchronized块 |
|
类锁 |
Class对象 |
使用同一Class对象的synchronized块 |
|
自定义锁 |
自定义对象 |
使用同一自定义对象的synchronized块 |
|
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圣经