13-Java语言核心-并发编程-同步机制详解

3 阅读16分钟

同步机制详解

一、知识概述

在多线程环境下,多个线程同时访问共享资源可能导致数据不一致问题。Java提供了多种同步机制来保证线程安全,包括synchronized关键字、volatile变量和CAS操作。理解这些同步机制的原理和适用场景是编写正确并发程序的基础。

同步机制概览

┌─────────────────────────────────────────────────────────────────────┐
│                    Java同步机制体系                                  │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                     线程安全保障                             │   │
│  ├─────────────────────────────────────────────────────────────┤   │
│  │                                                             │   │
│  │  1. 互斥同步                                                │   │
│  │     ┌─────────────┐   ┌─────────────┐   ┌─────────────┐    │   │
│  │     │ synchronized│   │   Reentrant │   │   Lock      │    │   │
│  │     │   关键字    │   │    Lock     │   │  支持类     │    │   │
│  │     └─────────────┘   └─────────────┘   └─────────────┘    │   │
│  │                                                             │   │
│  │  2. 非阻塞同步                                              │   │
│  │     ┌─────────────┐   ┌─────────────┐                      │   │
│  │     │    CAS      │   │ Atomic类    │                      │   │
│  │     │ 原子操作    │   │  原子变量   │                      │   │
│  │     └─────────────┘   └─────────────┘                      │   │
│  │                                                             │   │
│  │  3. 可见性保证                                              │   │
│  │     ┌─────────────┐   ┌─────────────┐   ┌─────────────┐    │   │
│  │     │  volatile   │   │   final     │   │  happens-   │    │   │
│  │     │   关键字    │   │   字段      │   │   before    │    │   │
│  │     └─────────────┘   └─────────────┘   └─────────────┘    │   │
│  │                                                             │   │
│  │  4. 无同步方案                                              │   │
│  │     ┌─────────────┐   ┌─────────────┐                      │   │
│  │     │ ThreadLocal │   │  不可变对象 │                      │   │
│  │     │ 线程本地    │   │  (immutable)│                      │   │
│  │     └─────────────┘   └─────────────┘                      │   │
│  │                                                             │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

线程安全问题

/**
 * 线程安全问题演示
 */
public class ThreadSafetyProblem {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== 线程安全问题演示 ===\n");
        
        // 不安全的计数器
        class UnsafeCounter {
            private int count = 0;
            
            public void increment() {
                count++;  // 非原子操作
            }
            
            public int getCount() {
                return count;
            }
        }
        
        UnsafeCounter counter = new UnsafeCounter();
        
        // 多线程并发递增
        Thread[] threads = new Thread[100];
        for (int i = 0; i < 100; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    counter.increment();
                }
            });
        }
        
        for (Thread t : threads) t.start();
        for (Thread t : threads) t.join();
        
        System.out.println("期望结果: 100000");
        System.out.println("实际结果: " + counter.getCount());
        System.out.println("问题原因: count++不是原子操作");
        System.out.println();
        
        /*
        count++的字节码:
        1. 读取count值到操作数栈
        2. 将常量1压栈
        3. 执行加法
        4. 将结果写回count
        
        多线程下可能发生:
        线程A读取count=0
        线程B读取count=0
        线程A计算count=1,写入
        线程B计算count=1,写入
        结果: 两次递增,但count只增加了1
        */
    }
}

二、知识点详细讲解

2.1 synchronized关键字

2.1.1 基本使用
/**
 * synchronized基本使用
 */
public class SynchronizedBasicDemo {
    
    public static void main(String[] args) {
        System.out.println("=== synchronized基本使用 ===\n");
        
        synchronizedMethodDemo();
        synchronizedBlockDemo();
        staticSynchronizedDemo();
    }
    
    /**
     * 同步方法
     */
    private static void synchronizedMethodDemo() {
        System.out.println("【同步方法】\n");
        
        class Counter {
            private int count = 0;
            
            // 同步实例方法 - 锁是this对象
            public synchronized void increment() {
                count++;
            }
            
            // 同步实例方法
            public synchronized void decrement() {
                count--;
            }
            
            public synchronized int getCount() {
                return count;
            }
        }
        
        System.out.println("实例同步方法:");
        System.out.println("  public synchronized void method() { ... }");
        System.out.println("  锁对象: this (当前实例)");
        System.out.println();
    }
    
    /**
     * 同步代码块
     */
    private static void synchronizedBlockDemo() {
        System.out.println("【同步代码块】\n");
        
        class Counter {
            private final Object lock = new Object();
            private int count = 0;
            
            public void increment() {
                // 同步代码块 - 指定锁对象
                synchronized (lock) {
                    count++;
                }
            }
            
            public void incrementThis() {
                // 使用this作为锁
                synchronized (this) {
                    count++;
                }
            }
        }
        
        System.out.println("同步代码块:");
        System.out.println("  synchronized (lockObject) { ... }");
        System.out.println("  锁对象: 括号内指定的对象");
        System.out.println();
        
        System.out.println("优点:");
        System.out.println("  1. 可以指定任意锁对象");
        System.out.println("  2. 减小锁粒度");
        System.out.println("  3. 避免锁整个方法");
        System.out.println();
    }
    
    /**
     * 静态同步方法
     */
    private static void staticSynchronizedDemo() {
        System.out.println("【静态同步方法】\n");
        
        class StaticCounter {
            private static int count = 0;
            
            // 同步静态方法 - 锁是Class对象
            public static synchronized void increment() {
                count++;
            }
            
            // 等价于
            public static void incrementBlock() {
                synchronized (StaticCounter.class) {
                    count++;
                }
            }
        }
        
        System.out.println("静态同步方法:");
        System.out.println("  public static synchronized void method() { ... }");
        System.out.println("  锁对象: Class对象 (StaticCounter.class)");
        System.out.println();
        
        System.out.println("说明:");
        System.out.println("  - 静态同步方法与实例同步方法使用不同的锁");
        System.out.println("  - 静态方法锁Class对象");
        System.out.println("  - 实例方法锁this对象");
        System.out.println("  - 两者互不影响");
        System.out.println();
    }
}
2.1.2 synchronized特性
/**
 * synchronized特性详解
 */
public class SynchronizedFeaturesDemo {
    
    public static void main(String[] args) {
        System.out.println("=== synchronized特性 ===\n");
        
        atomicityDemo();
        reentrancyDemo();
        visibilityDemo();
    }
    
    /**
     * 原子性
     */
    private static void atomicityDemo() {
        System.out.println("【原子性】\n");
        
        System.out.println("synchronized保证原子性:");
        System.out.println("  - 同一时刻只有一个线程能进入同步块");
        System.out.println("  - 代码块内的操作不会被中断");
        System.out.println();
        
        class SafeCounter {
            private int count = 0;
            
            public synchronized void increment() {
                count++;  // 现在是原子操作
            }
            
            public synchronized int getCount() {
                return count;
            }
        }
        
        System.out.println("示例: 安全的计数器");
        System.out.println("  synchronized确保count++的原子性");
        System.out.println();
    }
    
    /**
     * 可重入性
     */
    private static void reentrancyDemo() {
        System.out.println("【可重入性】\n");
        
        class ReentrantDemo {
            public synchronized void methodA() {
                System.out.println("methodA开始");
                methodB();  // 可重入调用
                System.out.println("methodA结束");
            }
            
            public synchronized void methodB() {
                System.out.println("methodB执行");
            }
        }
        
        System.out.println("可重入性说明:");
        System.out.println("  - 同一线程可重复获取同一把锁");
        System.out.println("  - 避免死锁");
        System.out.println("  - 实现原理: 锁计数器");
        System.out.println();
        
        System.out.println("示例:");
        System.out.println("  线程进入methodA,获取锁,计数=1");
        System.out.println("  线程调用methodB,再次获取锁,计数=2");
        System.out.println("  线程退出methodB,释放锁,计数=1");
        System.out.println("  线程退出methodA,释放锁,计数=0");
        System.out.println();
        
        System.out.println("可重入场景:");
        System.out.println("  1. 同步方法调用同步方法");
        System.out.println("  2. 子类同步方法调用父类同步方法");
        System.out.println();
    }
    
    /**
     * 可见性
     */
    private static void visibilityDemo() {
        System.out.println("【可见性】\n");
        
        System.out.println("synchronized保证可见性:");
        System.out.println("  - 获取锁: 清空工作内存,从主内存读取");
        System.out.println("  - 释放锁: 将工作内存写入主内存");
        System.out.println();
        
        System.out.println("happens-before关系:");
        System.out.println("  - 释放锁 happens-before 获取锁");
        System.out.println("  - 前一个线程的修改对后一个线程可见");
        System.out.println();
    }
}
2.1.3 synchronized原理
/**
 * synchronized底层原理
 */
public class SynchronizedPrincipleDemo {
    
    public static void main(String[] args) {
        System.out.println("=== synchronized底层原理 ===\n");
        
        monitorDemo();
        objectHeaderDemo();
        lockUpgradeDemo();
    }
    
    /**
     * Monitor机制
     */
    private static void monitorDemo() {
        System.out.println("【Monitor机制】\n");
        
        /*
        每个Java对象都有一个Monitor(监视器锁)
        
        Monitor结构:
        ┌─────────────────────────────────────┐
        │              Monitor                │
        ├─────────────────────────────────────┤
        │  _owner: 当前持有锁的线程           │
        │  _EntryList: 等待获取锁的线程队列   │
        │  _WaitSet: 调用wait()的线程队列     │
        │  _count: 锁计数器                   │
        └─────────────────────────────────────┘
        
        同步代码块的字节码:
        monitorenter  // 获取Monitor
        ...           // 同步代码
        monitorexit   // 释放Monitor
        */
        
        System.out.println("Monitor工作流程:");
        System.out.println();
        System.out.println("1. 线程执行monitorenter:");
        System.out.println("   - 如果Monitor的_owner为空,线程获取锁");
        System.out.println("   - 如果_owner是当前线程,_count加1(重入)");
        System.out.println("   - 否则线程进入_EntryList等待");
        System.out.println();
        
        System.out.println("2. 线程执行monitorexit:");
        System.out.println("   - _count减1");
        System.out.println("   - 如果_count为0,释放锁,_owner置空");
        System.out.println("   - 从_EntryList唤醒一个线程");
        System.out.println();
        
        System.out.println("3. 执行wait():");
        System.out.println("   - 线程释放锁");
        System.out.println("   - 线程进入_WaitSet");
        System.out.println();
        
        System.out.println("4. 执行notify():");
        System.out.println("   - 从_WaitSet移动一个线程到_EntryList");
        System.out.println("   - 等待获取锁");
        System.out.println();
    }
    
    /**
     * 对象头与Mark Word
     */
    private static void objectHeaderDemo() {
        System.out.println("【对象头与Mark Word】\n");
        
        /*
        Java对象内存布局:
        ┌─────────────────────────────────────┐
        │            对象头                    │
        │  ┌───────────────────────────────┐  │
        │  │        Mark Word (8字节)      │  │
        │  │   存储锁状态、GC年龄、哈希码   │  │
        │  └───────────────────────────────┘  │
        │  ┌───────────────────────────────┐  │
        │  │    类型指针 (4/8字节)         │  │
        │  │       指向类元数据             │  │
        │  └───────────────────────────────┘  │
        ├─────────────────────────────────────┤
        │           实例数据                   │
        ├─────────────────────────────────────┤
        │           对齐填充                   │
        └─────────────────────────────────────┘
        
        Mark Word结构 (64位JVM):
        ┌────────────────────────────────────────────────────────┐
        │                  锁状态          │ 内容                  │
        ├────────────────────────────────────────────────────────┤
        │ 无锁           │ hashcode | age | 0 | 01              │
        │ 偏向锁         │ thread ID | age | 1 | 01              │
        │ 轻量级锁       │ 指向栈中Lock Record的指针 | 00         │
        │ 重量级锁       │ 指向Monitor的指针 | 10                 │
        │ GC标记         │ 空 | 11                               │
        └────────────────────────────────────────────────────────┘
        */
        
        System.out.println("Mark Word存储信息:");
        System.out.println("  - 锁状态标志");
        System.out.println("  - 哈希码(未锁定时)");
        System.out.println("  - GC分代年龄");
        System.out.println("  - 偏向锁的线程ID");
        System.out.println("  - 锁记录指针/Monitor指针");
        System.out.println();
    }
    
    /**
     * 锁升级过程
     */
    private static void lockUpgradeDemo() {
        System.out.println("【锁升级过程】\n");
        
        /*
        锁升级: 偏向锁 -> 轻量级锁 -> 重量级锁
        升级是单向的,不可降级
        
        ┌─────────────────────────────────────────────────────────────┐
        │                        锁升级流程                            │
        ├─────────────────────────────────────────────────────────────┤
        │                                                             │
        │  无锁状态                                                   │
        │      │                                                      │
        │      ▼                                                      │
        │  ┌───────────┐                                             │
        │  │ 偏向锁    │  单线程重入,无竞争                         │
        │  │ Lock: 101 │  在Mark Word中记录线程ID                    │
        │  └─────┬─────┘                                             │
        │        │ 出现竞争                                          │
        │        ▼                                                    │
        │  ┌───────────┐                                             │
        │  │ 轻量级锁  │  多线程交替执行                             │
        │  │ Lock: 000 │  CAS将Mark Word替换为Lock Record指针       │
        │  └─────┬─────┘                                             │
        │        │ 自旋失败,竞争激烈                                │
        │        ▼                                                    │
        │  ┌───────────┐                                             │
        │  │ 重量级锁  │  多线程竞争激烈                             │
        │  │ Lock: 010 │  Monitor实现,线程阻塞                     │
        │  └───────────┘                                             │
        │                                                             │
        └─────────────────────────────────────────────────────────────┘
        */
        
        System.out.println("1. 偏向锁 (Biased Lock)");
        System.out.println("   - 适用: 单线程重入场景");
        System.out.println("   - 原理: Mark Word记录线程ID");
        System.out.println("   - 优点: 几乎无额外开销");
        System.out.println("   - 撤销: 有其他线程竞争时");
        System.out.println();
        
        System.out.println("2. 轻量级锁 (Lightweight Lock)");
        System.out.println("   - 适用: 多线程交替执行,竞争不激烈");
        System.out.println("   - 原理: CAS操作 + 自旋");
        System.out.println("   - Lock Record: 栈帧中的锁记录");
        System.out.println("   - 优点: 避免线程阻塞开销");
        System.out.println();
        
        System.out.println("3. 重量级锁 (Heavyweight Lock)");
        System.out.println("   - 适用: 竞争激烈");
        System.out.println("   - 原理: Monitor实现");
        System.out.println("   - 缺点: 线程阻塞/唤醒开销大");
        System.out.println();
        
        System.out.println("锁升级是JVM的优化,开发者无需关心");
        System.out.println("相关参数:");
        System.out.println("  -XX:+UseBiasedLocking     开启偏向锁(默认)");
        System.out.println("  -XX:BiasedLockingStartupDelay=4000  偏向锁启动延迟");
        System.out.println();
    }
}

2.2 volatile关键字

2.2.1 基本概念
/**
 * volatile关键字详解
 */
public class VolatileDemo {
    
    public static void main(String[] args) {
        System.out.println("=== volatile关键字 ===\n");
        
        visibilityDemo();
        orderingDemo();
        atomicityLimitation();
    }
    
    /**
     * 可见性保证
     */
    private static void visibilityDemo() throws InterruptedException {
        System.out.println("【可见性保证】\n");
        
        class VisibilityProblem {
            // 不使用volatile
            boolean running = true;
            
            void stop() {
                running = false;
            }
            
            void work() {
                while (running) {
                    // 工作循环
                }
                System.out.println("工作线程停止");
            }
        }
        
        class VisibilitySolution {
            // 使用volatile
            volatile boolean running = true;
            
            void stop() {
                running = false;
            }
            
            void work() {
                while (running) {
                    // 工作循环
                }
                System.out.println("工作线程停止(volatile)");
            }
        }
        
        System.out.println("可见性问题:");
        System.out.println("  - 线程有自己的工作内存(缓存)");
        System.out.println("  - 修改可能不会立即写入主内存");
        System.out.println("  - 其他线程可能看不到最新值");
        System.out.println();
        
        System.out.println("volatile解决方案:");
        System.out.println("  - 写操作: 立即写入主内存");
        System.out.println("  - 读操作: 从主内存读取最新值");
        System.out.println("  - 保证所有线程看到最新值");
        System.out.println();
        
        System.out.println("内存屏障:");
        System.out.println("  - StoreStore屏障: 禁止上面的写与下面的写重排序");
        System.out.println("  - StoreLoad屏障: 禁止上面的写与下面的读重排序");
        System.out.println("  - LoadLoad屏障: 禁止上面的读与下面的读重排序");
        System.out.println("  - LoadStore屏障: 禁止上面的读与下面的写重排序");
        System.out.println();
    }
    
    /**
     * 有序性保证
     */
    private static void orderingDemo() {
        System.out.println("【有序性保证】\n");
        
        /*
        指令重排序示例:
        
        初始: x = 0, y = 0
        线程1: x = 1; y = 1;
        线程2: r1 = y; r2 = x;
        
        可能的执行顺序(重排序后):
        线程1: y = 1; x = 1;  (重排序)
        线程2: r1 = y; r2 = x;
        
        结果: r1 = 1, r2 = 0 (不符合预期)
        */
        
        class ReorderingProblem {
            int x = 0;
            int y = 0;
            
            void writer() {
                x = 1;
                y = 1;  // 可能重排序到x=1之前
            }
            
            void reader() {
                int r1 = y;
                int r2 = x;
                // r1 = 1, r2 = 0 是可能的
            }
        }
        
        class ReorderingSolution {
            volatile int x = 0;
            volatile int y = 0;
            
            void writer() {
                x = 1;
                y = 1;  // volatile写,x=1不会被重排序到y=1之后
            }
            
            void reader() {
                int r1 = y;  // volatile读
                int r2 = x;  // 不会被重排序到y读之前
            }
        }
        
        System.out.println("指令重排序:");
        System.out.println("  - 编译器优化重排序");
        System.out.println("  - CPU指令级并行重排序");
        System.out.println("  - 内存系统重排序");
        System.out.println();
        
        System.out.println("volatile禁止重排序:");
        System.out.println("  - volatile写之前的操作不会重排序到之后");
        System.out.println("  - volatile读之后的操作不会重排序到之前");
        System.out.println();
        
        System.out.println("应用场景 - 双重检查锁单例:");
        System.out.println("  private volatile static Singleton instance;");
        System.out.println("  volatile防止对象初始化重排序");
        System.out.println();
    }
    
    /**
     * 原子性限制
     */
    private static void atomicityLimitation() {
        System.out.println("【原子性限制】\n");
        
        class VolatileCounter {
            private volatile int count = 0;
            
            public void increment() {
                count++;  // 仍然不是原子操作!
            }
            
            public int getCount() {
                return count;
            }
        }
        
        System.out.println("⚠️ volatile不保证原子性");
        System.out.println();
        
        System.out.println("count++分析:");
        System.out.println("  1. 读取count值 (volatile读,读主内存)");
        System.out.println("  2. 加1");
        System.out.println("  3. 写入count值 (volatile写,写主内存)");
        System.out.println();
        
        System.out.println("多线程问题:");
        System.out.println("  线程A: 读取count=0");
        System.out.println("  线程B: 读取count=0");
        System.out.println("  线程A: 加1,写入count=1");
        System.out.println("  线程B: 加1,写入count=1");
        System.out.println("  结果: 两次递增,count=1");
        System.out.println();
        
        System.out.println("volatile适用场景:");
        System.out.println("  ✅ 状态标志位");
        System.out.println("  ✅ 一次性安全发布");
        System.out.println("  ✅ 独立观察");
        System.out.println("  ✅ 开销较低的读-写锁策略");
        System.out.println();
        
        System.out.println("volatile不适用场景:");
        System.out.println("  ❌ 计数器(需要原子性)");
        System.out.println("  ❌ 依赖当前值的更新");
        System.out.println("  ❌ 复合操作");
        System.out.println();
    }
}
2.2.2 volatile应用场景
/**
 * volatile应用场景示例
 */
public class VolatileUseCasesDemo {
    
    public static void main(String[] args) {
        System.out.println("=== volatile应用场景 ===\n");
        
        statusFlagDemo();
        doubleCheckedLocking();
        cheapReadWriteLock();
    }
    
    /**
     * 状态标志位
     */
    private static void statusFlagDemo() {
        System.out.println("【状态标志位】\n");
        
        class Worker implements Runnable {
            private volatile boolean running = true;
            
            @Override
            public void run() {
                while (running) {
                    // 执行任务
                }
                System.out.println("Worker停止");
            }
            
            public void shutdown() {
                running = false;
            }
        }
        
        System.out.println("适用场景:");
        System.out.println("  - 线程停止标志");
        System.out.println("  - 状态切换开关");
        System.out.println("  - 初始化完成标志");
        System.out.println();
        
        System.out.println("示例:");
        System.out.println("  private volatile boolean initialized = false;");
        System.out.println("  private volatile boolean shutdown = false;");
        System.out.println();
    }
    
    /**
     * 双重检查锁单例
     */
    private static void doubleCheckedLocking() {
        System.out.println("【双重检查锁单例】\n");
        
        class Singleton {
            // volatile防止指令重排序
            private static volatile Singleton instance;
            
            private Singleton() {}
            
            public static Singleton getInstance() {
                if (instance == null) {  // 第一次检查
                    synchronized (Singleton.class) {
                        if (instance == null) {  // 第二次检查
                            instance = new Singleton();
                        }
                    }
                }
                return instance;
            }
        }
        
        System.out.println("为什么要用volatile?");
        System.out.println();
        
        System.out.println("instance = new Singleton() 分三步:");
        System.out.println("  1. 分配内存空间");
        System.out.println("  2. 初始化对象");
        System.out.println("  3. 将引用指向内存");
        System.out.println();
        
        System.out.println("重排序问题:");
        System.out.println("  可能重排序为: 1 -> 3 -> 2");
        System.out.println("  其他线程看到instance != null但对象未初始化");
        System.out.println();
        
        System.out.println("volatile解决:");
        System.out.println("  volatile禁止 2 和 3 重排序");
        System.out.println("  保证对象完全初始化后才对其他线程可见");
        System.out.println();
    }
    
    /**
     * 开销较低的读-写锁
     */
    private static void cheapReadWriteLock() {
        System.out.println("【开销较低的读-写锁】\n");
        
        class CheapReadWriteLock<T> {
            private volatile T value;
            
            public T getValue() {
                return value;  // volatile读,无锁
            }
            
            public synchronized void setValue(T value) {
                this.value = value;  // volatile写 + synchronized
            }
        }
        
        System.out.println("模式:");
        System.out.println("  读: 直接读volatile变量(无锁,高吞吐)");
        System.out.println("  写: synchronized保证原子性 + volatile保证可见性");
        System.out.println();
        
        System.out.println("适用场景:");
        System.out.println("  - 读多写少");
        System.out.println("  - 写操作需要原子性");
        System.out.println("  - 读操作不需要最新值");
        System.out.println();
        
        System.out.println("示例:");
        System.out.println("  class Config {");
        System.out.println("    private volatile String config;");
        System.out.println("    public String getConfig() { return config; }");
        System.out.println("    public synchronized void setConfig(String c) { config = c; }");
        System.out.println("  }");
        System.out.println();
    }
}

2.3 CAS操作

2.3.1 CAS原理
import java.util.concurrent.atomic.*;

/**
 * CAS (Compare-And-Swap) 操作详解
 */
public class CASDemo {
    
    public static void main(String[] args) {
        System.out.println("=== CAS操作详解 ===\n");
        
        casPrinciple();
        casInJava();
        casProblem();
    }
    
    /**
     * CAS原理
     */
    private static void casPrinciple() {
        System.out.println("【CAS原理】\n");
        
        /*
        CAS (Compare-And-Swap):
        
        伪代码:
        boolean cas(int *addr, int expected, int new_value) {
            if (*addr == expected) {
                *addr = new_value;
                return true;
            }
            return false;
        }
        
        特点:
        1. 原子性: 整个操作是原子的
        2. 无锁: 不需要获取锁
        3. 硬件支持: CPU指令级别的原子操作
        */
        
        System.out.println("CAS三个操作数:");
        System.out.println("  V (Value): 内存值");
        System.out.println("  E (Expected): 预期值");
        System.out.println("  N (New): 新值");
        System.out.println();
        
        System.out.println("CAS执行过程:");
        System.out.println("  如果 V == E,则 V = N,返回成功");
        System.out.println("  如果 V != E,则不做任何操作,返回失败");
        System.out.println();
        
        System.out.println("CPU指令支持:");
        System.out.println("  x86: CMPXCHG指令");
        System.out.println("  ARM: LDXR/STXR指令");
        System.out.println();
        
        System.out.println("JVM实现:");
        System.out.println("  Unsafe类的compareAndSwapXxx方法");
        System.out.println("  native方法,调用底层硬件指令");
        System.out.println();
    }
    
    /**
     * Java中的CAS
     */
    private static void casInJava() {
        System.out.println("【Java中的CAS】\n");
        
        // AtomicInteger示例
        AtomicInteger atomicInt = new AtomicInteger(0);
        
        // CAS操作
        boolean success = atomicInt.compareAndSet(0, 1);
        System.out.println("CAS(0, 1) 成功: " + success);
        System.out.println("当前值: " + atomicInt.get());
        
        success = atomicInt.compareAndSet(0, 2);
        System.out.println("CAS(0, 2) 成功: " + success);
        System.out.println("当前值: " + atomicInt.get());
        System.out.println();
        
        System.out.println("Atomic类:");
        System.out.println("  AtomicInteger");
        System.out.println("  AtomicLong");
        System.out.println("  AtomicBoolean");
        System.out.println("  AtomicReference<V>");
        System.out.println("  AtomicIntegerArray");
        System.out.println("  AtomicLongArray");
        System.out.println("  AtomicReferenceArray<V>");
        System.out.println("  AtomicIntegerFieldUpdater<T>");
        System.out.println("  AtomicLongFieldUpdater<T>");
        System.out.println("  AtomicReferenceFieldUpdater<T,V>");
        System.out.println("  AtomicStampedReference<V>");
        System.out.println("  AtomicMarkableReference<V>");
        System.out.println();
        
        System.out.println("常用方法:");
        System.out.println("  compareAndSet(expected, new)  CAS操作");
        System.out.println("  getAndIncrement()            原子递增并返回旧值");
        System.out.println("  incrementAndGet()            原子递增并返回新值");
        System.out.println("  getAndAdd(delta)            原子增加并返回旧值");
        System.out.println("  addAndGet(delta)            原子增加并返回新值");
        System.out.println();
        
        // 模拟CAS实现
        simulateCAS();
    }
    
    /**
     * 模拟CAS实现
     */
    private static void simulateCAS() {
        System.out.println("【模拟CAS实现】\n");
        
        class SimulatedCAS {
            private int value;
            
            public SimulatedCAS(int value) {
                this.value = value;
            }
            
            // 模拟CAS操作(实际需要硬件支持)
            public synchronized boolean compareAndSwap(int expected, int newValue) {
                if (value == expected) {
                    value = newValue;
                    return true;
                }
                return false;
            }
            
            public int get() {
                return value;
            }
        }
        
        class CASCounter {
            private SimulatedCAS cas = new SimulatedCAS(0);
            
            public void increment() {
                int oldValue;
                int newValue;
                do {
                    oldValue = cas.get();
                    newValue = oldValue + 1;
                } while (!cas.compareAndSwap(oldValue, newValue));
            }
            
            public int get() {
                return cas.get();
            }
        }
        
        System.out.println("CAS实现计数器:");
        System.out.println("  do {");
        System.out.println("    old = cas.get();");
        System.out.println("    new = old + 1;");
        System.out.println("  } while (!cas.compareAndSwap(old, new));");
        System.out.println();
        
        System.out.println("说明:");
        System.out.println("  - 循环尝试直到成功");
        System.out.println("  - 无锁设计");
        System.out.println("  - 适合低竞争场景");
        System.out.println();
    }
    
    /**
     * CAS问题
     */
    private static void casProblem() {
        System.out.println("【CAS的问题】\n");
        
        System.out.println("1. ABA问题");
        System.out.println("   场景:");
        System.out.println("     线程1读取V=A");
        System.out.println("     线程2将V改为B,再改回A");
        System.out.println("     线程1执行CAS(A, C),成功");
        System.out.println("   问题: V实际上被修改过");
        System.out.println();
        
        System.out.println("   解决方案: AtomicStampedReference");
        AtomicStampedReference<Integer> stampedRef = 
            new AtomicStampedReference<>(100, 0);
        
        int[] stampHolder = new int[1];
        Integer ref = stampedRef.get(stampHolder);
        System.out.println("   值: " + ref + ", 版本: " + stampHolder[0]);
        stampedRef.compareAndSet(100, 101, stampHolder[0], stampHolder[0] + 1);
        System.out.println();
        
        System.out.println("2. 自旋开销");
        System.out.println("   问题: 高竞争时CAS失败率高,导致大量自旋");
        System.out.println("   解决: 使用自适应自旋或退化为锁");
        System.out.println();
        
        System.out.println("3. 只能保证一个变量的原子性");
        System.out.println("   问题: 无法同时对多个变量进行CAS操作");
        System.out.println("   解决: 将多个变量封装为一个对象");
        System.out.println("         使用AtomicReference");
        System.out.println();
    }
}
2.3.2 Atomic类详解
import java.util.concurrent.atomic.*;
import java.util.function.*;

/**
 * Atomic类详解
 */
public class AtomicClassesDemo {
    
    public static void main(String[] args) {
        System.out.println("=== Atomic类详解 ===\n");
        
        basicAtomicDemo();
        atomicReferenceDemo();
        atomicFieldUpdaterDemo();
        atomicPerformanceDemo();
    }
    
    /**
     * 基本Atomic类
     */
    private static void basicAtomicDemo() {
        System.out.println("【基本Atomic类】\n");
        
        // AtomicInteger
        AtomicInteger atomicInt = new AtomicInteger(0);
        
        // 基本操作
        atomicInt.set(10);
        System.out.println("set(10): " + atomicInt.get());
        
        atomicInt.lazySet(20);  // 延迟设置,性能更好但不保证立即可见
        System.out.println("lazySet(20): " + atomicInt.get());
        
        // 原子更新
        System.out.println("getAndIncrement(): " + atomicInt.getAndIncrement());  // 返回20
        System.out.println("incrementAndGet(): " + atomicInt.incrementAndGet());  // 返回22
        
        System.out.println("getAndAdd(10): " + atomicInt.getAndAdd(10));  // 返回22
        System.out.println("addAndGet(10): " + atomicInt.addAndGet(10));  // 返回42
        
        // 条件更新
        System.out.println("compareAndSet(42, 50): " + atomicInt.compareAndSet(42, 50));
        System.out.println("当前值: " + atomicInt.get());
        
        // 函数式更新
        int result = atomicInt.updateAndGet(x -> x * 2);
        System.out.println("updateAndGet(x -> x * 2): " + result);
        
        result = atomicInt.accumulateAndGet(10, (x, y) -> x + y);
        System.out.println("accumulateAndGet(10, (x,y)->x+y): " + result);
        System.out.println();
    }
    
    /**
     * AtomicReference
     */
    private static void atomicReferenceDemo() {
        System.out.println("【AtomicReference】\n");
        
        class User {
            String name;
            int age;
            
            User(String name, int age) {
                this.name = name;
                this.age = age;
            }
            
            @Override
            public String toString() {
                return name + "(" + age + ")";
            }
        }
        
        AtomicReference<User> userRef = new AtomicReference<>(new User("张三", 20));
        
        System.out.println("初始用户: " + userRef.get());
        
        User oldUser = userRef.get();
        User newUser = new User("李四", 25);
        
        boolean success = userRef.compareAndSet(oldUser, newUser);
        System.out.println("CAS更新: " + success);
        System.out.println("当前用户: " + userRef.get());
        
        // 原子更新
        userRef.updateAndGet(u -> new User(u.name, u.age + 1));
        System.out.println("年龄+1: " + userRef.get());
        System.out.println();
        
        // AtomicStampedReference解决ABA问题
        System.out.println("【AtomicStampedReference】\n");
        
        AtomicStampedReference<Integer> stampedRef = 
            new AtomicStampedReference<>(100, 0);
        
        int[] stamp = new int[1];
        Integer value = stampedRef.get(stamp);
        System.out.println("值: " + value + ", 版本: " + stamp[0]);
        
        // 尝试更新
        boolean updated = stampedRef.compareAndSet(100, 101, stamp[0], stamp[0] + 1);
        System.out.println("更新成功: " + updated);
        
        value = stampedRef.get(stamp);
        System.out.println("值: " + value + ", 版本: " + stamp[0]);
        
        // 使用旧版本更新(会失败)
        updated = stampedRef.compareAndSet(101, 102, 0, 1);
        System.out.println("使用旧版本更新成功: " + updated);
        System.out.println();
    }
    
    /**
     * AtomicIntegerFieldUpdater
     */
    private static void atomicFieldUpdaterDemo() {
        System.out.println("【AtomicIntegerFieldUpdater】\n");
        
        class Person {
            volatile String name;
            volatile int age;  // 必须是volatile
            
            Person(String name, int age) {
                this.name = name;
                this.age = age;
            }
        }
        
        // 创建字段更新器
        AtomicIntegerFieldUpdater<Person> ageUpdater = 
            AtomicIntegerFieldUpdater.newUpdater(Person.class, "age");
        
        Person person = new Person("王五", 30);
        
        System.out.println("初始年龄: " + person.age);
        
        ageUpdater.incrementAndGet(person);
        System.out.println("incrementAndGet: " + person.age);
        
        ageUpdater.compareAndSet(person, 31, 35);
        System.out.println("CAS更新后: " + person.age);
        
        System.out.println();
        System.out.println("使用场景:");
        System.out.println("  - 已有类无法修改,需要对字段进行原子操作");
        System.out.println("  - 节省内存(不需要创建Atomic对象)");
        System.out.println();
        
        System.out.println("要求:");
        System.out.println("  - 字段必须是volatile");
        System.out.println("  - 字段必须可访问");
        System.out.println("  - 只能是int/long类型");
        System.out.println();
    }
    
    /**
     * Atomic性能对比
     */
    private static void atomicPerformanceDemo() throws InterruptedException {
        System.out.println("【Atomic性能对比】\n");
        
        // synchronized vs AtomicInteger
        class SyncCounter {
            private int count = 0;
            
            public synchronized void increment() {
                count++;
            }
            
            public int getCount() {
                return count;
            }
        }
        
        int threadCount = 10;
        int incrementsPerThread = 1000000;
        
        // synchronized测试
        SyncCounter syncCounter = new SyncCounter();
        long start = System.currentTimeMillis();
        
        Thread[] syncThreads = new Thread[threadCount];
        for (int i = 0; i < threadCount; i++) {
            syncThreads[i] = new Thread(() -> {
                for (int j = 0; j < incrementsPerThread; j++) {
                    syncCounter.increment();
                }
            });
        }
        
        for (Thread t : syncThreads) t.start();
        for (Thread t : syncThreads) t.join();
        
        long syncTime = System.currentTimeMillis() - start;
        System.out.println("synchronized: " + syncTime + "ms, 结果: " + syncCounter.getCount());
        
        // AtomicInteger测试
        AtomicInteger atomicCounter = new AtomicInteger(0);
        start = System.currentTimeMillis();
        
        Thread[] atomicThreads = new Thread[threadCount];
        for (int i = 0; i < threadCount; i++) {
            atomicThreads[i] = new Thread(() -> {
                for (int j = 0; j < incrementsPerThread; j++) {
                    atomicCounter.incrementAndGet();
                }
            });
        }
        
        for (Thread t : atomicThreads) t.start();
        for (Thread t : atomicThreads) t.join();
        
        long atomicTime = System.currentTimeMillis() - start;
        System.out.println("AtomicInteger: " + atomicTime + "ms, 结果: " + atomicCounter.get());
        
        // LongAdder测试(高并发更优)
        LongAdder longAdder = new LongAdder();
        start = System.currentTimeMillis();
        
        Thread[] adderThreads = new Thread[threadCount];
        for (int i = 0; i < threadCount; i++) {
            adderThreads[i] = new Thread(() -> {
                for (int j = 0; j < incrementsPerThread; j++) {
                    longAdder.increment();
                }
            });
        }
        
        for (Thread t : adderThreads) t.start();
        for (Thread t : adderThreads) t.join();
        
        long adderTime = System.currentTimeMillis() - start;
        System.out.println("LongAdder: " + adderTime + "ms, 结果: " + longAdder.sum());
        
        System.out.println();
        System.out.println("结论:");
        System.out.println("  - 低竞争: AtomicInteger性能较好");
        System.out.println("  - 高竞争: LongAdder性能更优");
        System.out.println("  - LongAdder使用分段累加,减少竞争");
        System.out.println();
    }
}

三、可运行Java代码示例

完整示例:线程安全计数器对比

import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

/**
 * 线程安全计数器完整示例
 */
public class ThreadSafeCounterDemo {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== 线程安全计数器对比 ===\n");
        
        // 1. 不安全的计数器
        testCounter("不安全计数器", new UnsafeCounter());
        
        // 2. synchronized计数器
        testCounter("synchronized计数器", new SynchronizedCounter());
        
        // 3. ReentrantLock计数器
        testCounter("ReentrantLock计数器", new LockCounter());
        
        // 4. AtomicInteger计数器
        testCounter("AtomicInteger计数器", new AtomicCounter());
        
        // 5. LongAdder计数器
        testCounter("LongAdder计数器", new LongAdderCounter());
        
        // 6. 无锁CAS计数器
        testCounter("CAS计数器", new CASCounter());
    }
    
    interface Counter {
        void increment();
        int getCount();
    }
    
    static void testCounter(String name, Counter counter) throws InterruptedException {
        int threadCount = 10;
        int incrementsPerThread = 100000;
        CountDownLatch latch = new CountDownLatch(threadCount);
        
        long start = System.currentTimeMillis();
        
        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                for (int j = 0; j < incrementsPerThread; j++) {
                    counter.increment();
                }
                latch.countDown();
            }).start();
        }
        
        latch.await();
        long elapsed = System.currentTimeMillis() - start;
        
        int expected = threadCount * incrementsPerThread;
        int actual = counter.getCount();
        boolean correct = (expected == actual);
        
        System.out.printf("%-25s 耗时: %4dms, 结果: %7d/%7d %s%n",
            name, elapsed, actual, expected, correct ? "✅" : "❌");
    }
    
    // 不安全的计数器
    static class UnsafeCounter implements Counter {
        private int count = 0;
        
        @Override
        public void increment() {
            count++;
        }
        
        @Override
        public int getCount() {
            return count;
        }
    }
    
    // synchronized计数器
    static class SynchronizedCounter implements Counter {
        private int count = 0;
        
        @Override
        public synchronized void increment() {
            count++;
        }
        
        @Override
        public synchronized int getCount() {
            return count;
        }
    }
    
    // ReentrantLock计数器
    static class LockCounter implements Counter {
        private int count = 0;
        private final ReentrantLock lock = new ReentrantLock();
        
        @Override
        public void increment() {
            lock.lock();
            try {
                count++;
            } finally {
                lock.unlock();
            }
        }
        
        @Override
        public int getCount() {
            lock.lock();
            try {
                return count;
            } finally {
                lock.unlock();
            }
        }
    }
    
    // AtomicInteger计数器
    static class AtomicCounter implements Counter {
        private AtomicInteger count = new AtomicInteger(0);
        
        @Override
        public void increment() {
            count.incrementAndGet();
        }
        
        @Override
        public int getCount() {
            return count.get();
        }
    }
    
    // LongAdder计数器
    static class LongAdderCounter implements Counter {
        private LongAdder count = new LongAdder();
        
        @Override
        public void increment() {
            count.increment();
        }
        
        @Override
        public int getCount() {
            return count.intValue();
        }
    }
    
    // CAS计数器
    static class CASCounter implements Counter {
        private AtomicInteger count = new AtomicInteger(0);
        
        @Override
        public void increment() {
            int oldVal, newVal;
            do {
                oldVal = count.get();
                newVal = oldVal + 1;
            } while (!count.compareAndSet(oldVal, newVal));
        }
        
        @Override
        public int getCount() {
            return count.get();
        }
    }
}

四、总结与最佳实践

核心要点回顾

机制特性适用场景
synchronized互斥性、可见性、可重入复合操作、需要原子性
volatile可见性、有序性状态标志、单例双重检查
CAS原子性、无锁计数器、低竞争场景

最佳实践

  1. 选择正确的同步机制

    • 复合操作用synchronized或Lock
    • 状态标志用volatile
    • 计数器用Atomic或LongAdder
  2. 避免过度同步

    • 同步块尽量短
    • 避免在同步块中调用外部方法
  3. 正确使用volatile

    • 只用于状态标志
    • 不用于依赖当前值的更新
  4. 理解锁升级

    • JVM自动优化
    • 关注竞争程度

相关JVM参数

# 偏向锁
-XX:+UseBiasedLocking           # 开启偏向锁(默认)
-XX:BiasedLockingStartupDelay=0 # 偏向锁启动延迟

# 自旋锁
-XX:+UseSpinning       # 开启自旋(默认)
-XX:SpinWaitIterations=10  # 自旋次数

# 逃逸分析
-XX:+DoEscapeAnalysis  # 开启逃逸分析(默认)

扩展阅读

  • 《Java并发编程实战》:同步机制章节
  • 《深入理解Java虚拟机》:锁优化章节
  • JSR-133:Java内存模型规范