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