本文目录导读:

我来详细说明Java线程同步的规范流程,包括最佳实践和常见模式。
同步方法选择规范
1 优先选择高级并发工具
// ✅ 推荐:使用 java.util.concurrent 包
public class ConcurrentCounter {
private final AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
}
2 使用synchronized的场景
public class ThreadSafeList {
private final List<String> list = new ArrayList<>();
// 明确指定锁对象
public synchronized void add(String item) {
list.add(item);
}
// 或者使用显式锁对象
private final Object lock = new Object();
public void remove(String item) {
synchronized (lock) {
list.remove(item);
}
}
}
锁的使用规范
1 ReentrantLock规范使用
public class BankAccount {
private final ReentrantLock lock = new ReentrantLock();
private double balance;
public void transfer(double amount) {
lock.lock(); // 必须在try之前获取锁
try {
// 业务逻辑
balance += amount;
} finally {
lock.unlock(); // 必须在finally中释放
}
}
// 带超时的锁
public boolean tryTransfer(double amount, long timeout)
throws InterruptedException {
if (lock.tryLock(timeout, TimeUnit.MILLISECONDS)) {
try {
balance += amount;
return true;
} finally {
lock.unlock();
}
}
return false;
}
}
2 ReadWriteLock使用规范
public class Cache<K, V> {
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Map<K, V> map = new HashMap<>();
public V get(K key) {
rwLock.readLock().lock();
try {
return map.get(key);
} finally {
rwLock.readLock().unlock();
}
}
public void put(K key, V value) {
rwLock.writeLock().lock();
try {
map.put(key, value);
} finally {
rwLock.writeLock().unlock();
}
}
}
等待/通知模式规范
1 标准wait/notify模式
public class BlockingQueue<T> {
private final Queue<T> queue = new LinkedList<>();
private final int capacity;
public synchronized void put(T item) throws InterruptedException {
while (queue.size() == capacity) {
wait(); // 必须使用while循环检查条件
}
queue.add(item);
notifyAll(); // 优先使用notifyAll而非notify
}
public synchronized T take() throws InterruptedException {
while (queue.isEmpty()) {
wait();
}
T item = queue.poll();
notifyAll();
return item;
}
}
2 Condition使用规范
public class ConditionExample {
private final ReentrantLock lock = new ReentrantLock();
private final Condition notEmpty = lock.newCondition();
private final Condition notFull = lock.newCondition();
private final Queue<Object> queue = new LinkedList<>();
private final int maxSize = 10;
public void put(Object item) throws InterruptedException {
lock.lock();
try {
while (queue.size() == maxSize) {
notFull.await();
}
queue.add(item);
notEmpty.signalAll();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (queue.isEmpty()) {
notEmpty.await();
}
Object item = queue.poll();
notFull.signalAll();
return item;
} finally {
lock.unlock();
}
}
}
可见性保证规范
1 volatile的正确使用
public class FlagExample {
// volatile确保可见性,但不保证原子性
private volatile boolean running = true;
public void stop() {
running = false; // 单线程写操作安全
}
public void run() {
while (running) { // 多线程读操作
// 业务逻辑
}
}
}
2 final的线程安全使用
public class ImmutableObject {
private final int id;
private final String name;
private final List<String> items;
public ImmutableObject(int id, String name, List<String> items) {
this.id = id;
this.name = name;
// 防御性复制
this.items = Collections.unmodifiableList(new ArrayList<>(items));
}
// 只有getter,没有setter
public int getId() { return id; }
public String getName() { return name; }
public List<String> getItems() { return items; }
}
线程安全类设计规范
1 线程安全单例
public class ThreadSafeSingleton {
// 枚举方式(最推荐)
private enum Singleton {
INSTANCE;
private final ThreadSafeSingleton instance;
Singleton() {
instance = new ThreadSafeSingleton();
}
public ThreadSafeSingleton getInstance() {
return instance;
}
}
public static ThreadSafeSingleton getInstance() {
return Singleton.INSTANCE.getInstance();
}
}
// 双重检查锁定(适用于低版本Java)
public class DoubleCheckedSingleton {
private static volatile DoubleCheckedSingleton instance;
private DoubleCheckedSingleton() {}
public static DoubleCheckedSingleton getInstance() {
if (instance == null) {
synchronized (DoubleCheckedSingleton.class) {
if (instance == null) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
}
并发容器使用规范
public class ConcurrentCollectionExample {
// 优先使用并发容器而非同步容器
private final ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
private final CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
private final BlockingQueue<String> queue = new LinkedBlockingQueue<>(100);
// 原子性的复合操作
public void putIfAbsent(String key, String value) {
map.putIfAbsent(key, value); // 原子操作
}
// 避免在迭代时修改
public void safeIteration() {
for (String item : list) { // CopyOnWriteArrayList允许迭代时修改
System.out.println(item);
}
}
}
性能优化规范
1 锁粒度控制
public class LockGranularity {
// ❌ 锁粒度过大
public synchronized void processAll() {
longRunningOperation1();
fastOperation();
longRunningOperation2();
}
// ✅ 锁粒度适中
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void processOptimized() {
longRunningOperation1(); // 不需要同步
synchronized (lock1) {
fastOperation(); // 只需要同步关键部分
}
longRunningOperation2(); // 不需要同步
}
}
最佳实践总结
1 同步选择建议
| 场景 | 推荐方案 | 说明 |
|---|---|---|
| 简单计数 | AtomicInteger | 无锁CAS操作 |
| 少量共享数据 | synchronized | 实现简单,自动管理 |
| 复杂并发控制 | ReentrantLock | 灵活的锁机制 |
| 读写分离 | ReadWriteLock | 读多写少场景 |
| 生产者消费者 | BlockingQueue | 自带等待通知机制 |
2 常见陷阱避免
public class CommonPitfalls {
// ❌ 不要锁字符串常量
private final String LOCK = new String("LOCK"); // 应该使用new创建
// ✅ 正确的锁对象
private final Object lock = new Object();
// ❌ 不要在同步块中调用sleep
public synchronized void badMethod() throws InterruptedException {
Thread.sleep(1000); // 持有锁时sleep
}
// ✅ 正确的做法
public void goodMethod() throws InterruptedException {
longRunningOperation();
synchronized (lock) {
criticalSection();
}
}
}
3 检查清单
- 锁获取/释放:确保配对,在finally中释放
- 等待条件:始终使用while循环检查
- 可见性:使用volatile或加锁确保可见性
- 原子性:对复合操作使用同步
- 死锁预防:按固定顺序获取多个锁
- 性能考虑:最小化同步块范围
遵循这些规范可以构建出既安全又高效的并发Java程序。