Java并发编程,从线程安全到死锁避免的实战解析
Java并发编程是构建高性能系统的核心技能,但也伴随着复杂的挑战。本文通过实际代码示例,系统讲解线程安全、死锁、资源竞争等常见问题的解决方案,并深入探讨如何利用Java并发工具包(java.util.concurrent)构建健壮的并发程序。
一、线程安全问题与解决方案
1.1 共享资源的竞态条件(Race Condition)
问题现象:
多个线程同时修改共享变量,导致数据不一致。
public class Counter {private int count = 0;public void increment() {count++; // 非原子操作}public int getCount() {return count;}
}// 测试代码
public class RaceConditionTest {public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();Thread t1 = new Thread(() -> {for (int i = 0; i < 10000; i++) {counter.increment();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 10000; i++) {counter.increment();}});t1.start();t2.start();t1.join();t2.join();System.out.println("Expected: 20000, Actual: " + counter.getCount());}
}
输出结果:
Expected: 20000, Actual: 18437
解决方案:
使用synchronized
关键字
public class SafeCounter {private int count = 0;public synchronized void increment() {count++;}public synchronized int getCount() {return count;}
}
使用ReentrantLock
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class SafeCounter {private int count = 0;private Lock lock = new ReentrantLock();public void increment() {lock.lock();try {count++;} finally {lock.unlock();}}public int getCount() {lock.lock();try {return count;} finally {lock.unlock();}}
}
使用AtomicInteger
import java.util.concurrent.atomic.AtomicInteger;public class SafeCounter {private AtomicInteger count = new AtomicInteger(0);public void increment() {count.incrementAndGet(); // 原子操作}public int getCount() {return count.get();}
}
二、死锁问题与避免策略
2.1 死锁产生的条件
四个必要条件:
- 互斥(Mutual Exclusion)
- 请求与保持(Hold and Wait)
- 不可抢占(No Preemption)