Java线程同步 #

一、线程安全问题 #

1.1 问题示例 #

java
public class Counter {
    private int count = 0;
    
    public void increment() {
        count++;  // 非原子操作:读取、修改、写入
    }
    
    public int getCount() {
        return count;
    }
}

// 多线程下可能丢失更新

1.2 竞态条件 #

当多个线程访问共享资源,结果取决于执行顺序时,就存在竞态条件。

二、synchronized关键字 #

2.1 同步方法 #

java
public class Counter {
    private int count = 0;
    
    public synchronized void increment() {
        count++;
    }
    
    public synchronized int getCount() {
        return count;
    }
}

2.2 同步代码块 #

java
public class Counter {
    private int count = 0;
    private final Object lock = new Object();
    
    public void increment() {
        synchronized (lock) {
            count++;
        }
    }
    
    public void increment2() {
        synchronized (this) {  // 使用this作为锁
            count++;
        }
    }
}

2.3 静态同步方法 #

java
public class Counter {
    private static int count = 0;
    
    public static synchronized void increment() {
        count++;  // 锁是Counter.class
    }
    
    public static void increment2() {
        synchronized (Counter.class) {
            count++;
        }
    }
}

2.4 synchronized特性 #

  • 互斥性:同一时刻只有一个线程可以执行
  • 可见性:线程释放锁时将修改刷新到主内存
  • 可重入性:同一线程可多次获取同一把锁

三、Lock接口 #

3.1 基本使用 #

java
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Counter {
    private int count = 0;
    private final Lock lock = new ReentrantLock();
    
    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();  // 必须在finally中释放锁
        }
    }
}

3.2 tryLock #

java
Lock lock = new ReentrantLock();

if (lock.tryLock()) {
    try {
        // 获取锁成功
    } finally {
        lock.unlock();
    }
} else {
    // 获取锁失败
}

// 带超时
if (lock.tryLock(1, TimeUnit.SECONDS)) {
    try {
        // 获取锁成功
    } finally {
        lock.unlock();
    }
}

3.3 公平锁 #

java
Lock fairLock = new ReentrantLock(true);  // 公平锁
Lock unfairLock = new ReentrantLock(false);  // 非公平锁(默认)

3.4 ReadWriteLock #

java
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Cache {
    private final Map<String, Object> map = new HashMap<>();
    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
    
    public Object get(String key) {
        rwLock.readLock().lock();
        try {
            return map.get(key);
        } finally {
            rwLock.readLock().unlock();
        }
    }
    
    public void put(String key, Object value) {
        rwLock.writeLock().lock();
        try {
            map.put(key, value);
        } finally {
            rwLock.writeLock().unlock();
        }
    }
}

四、synchronized vs Lock #

特性 synchronized Lock
获取锁 自动 手动
释放锁 自动 手动(finally)
公平性 非公平 可选
中断 不支持 支持lockInterruptibly
超时 不支持 支持tryLock
条件变量 单一 多个Condition

五、volatile关键字 #

5.1 可见性 #

java
public class Flag {
    private volatile boolean running = true;
    
    public void stop() {
        running = false;
    }
    
    public void doWork() {
        while (running) {
            // 工作
        }
    }
}

5.2 禁止指令重排 #

java
public class Singleton {
    private static volatile Singleton instance;
    
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

5.3 volatile局限性 #

  • 不保证原子性
  • 适用于一写多读场景

六、原子类 #

6.1 AtomicInteger #

java
import java.util.concurrent.atomic.AtomicInteger;

public class Counter {
    private AtomicInteger count = new AtomicInteger(0);
    
    public void increment() {
        count.incrementAndGet();
    }
    
    public int getCount() {
        return count.get();
    }
}

6.2 其他原子类 #

java
AtomicBoolean atomicBool = new AtomicBoolean(false);
AtomicLong atomicLong = new AtomicLong(0);
AtomicReference<String> atomicRef = new AtomicReference<>("initial");

// 数组
AtomicIntegerArray atomicArr = new AtomicIntegerArray(10);

// 字段更新器
AtomicIntegerFieldUpdater<User> updater = 
    AtomicIntegerFieldUpdater.newUpdater(User.class, "age");

6.3 CAS操作 #

java
AtomicInteger atomic = new AtomicInteger(0);

// 比较并交换
boolean success = atomic.compareAndSet(0, 1);

// 自定义操作
int result = atomic.updateAndGet(x -> x * 2);

七、总结 #

方式 特点
synchronized 简单,自动管理锁
Lock 灵活,支持超时和中断
volatile 保证可见性,不保证原子性
原子类 无锁,高性能

线程同步要点:

  • 根据场景选择合适的同步方式
  • Lock需要手动释放锁
  • volatile适用于一写多读
  • 原子类适合简单计数场景
最后更新:2026-03-26