本文目录导读:

下面我为你提供几个经典的Java并发BUG案例,每个案例都附有代码示例和详细分析,帮助你理解并发问题的本质。
案例1:可见性问题(Visibility)
代码示例
public class VisibilityBug {
private static boolean running = true;
public static void main(String[] args) throws InterruptedException {
Thread worker = new Thread(() -> {
while (running) {
// 空循环等待标志位改变
}
System.out.println("Worker线程结束");
});
worker.start();
Thread.sleep(1000);
running = false; // 主线程修改标志位
System.out.println("主线程已修改标志位");
worker.join();
}
}
BUG分析
- 问题:主线程修改
running = false后,Worker线程可能永远无法退出while循环 - 原因:Worker线程可能将
running的值缓存在CPU缓存中,没有及时看到主线程的修改 - 解决方案:使用
volatile关键字或synchronized保证可见性
修复方法
private static volatile boolean running = true; // 添加volatile
案例2:非原子操作(Race Condition)
代码示例
public class CounterRaceCondition {
private int count = 0;
public void increment() {
count++; // 非原子操作:读-改-写
}
public static void main(String[] args) throws InterruptedException {
CounterRaceCondition counter = new CounterRaceCondition();
// 创建100个线程,每个线程递增1000次
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 100; i++) {
Thread t = new Thread(() -> {
for (int j = 0; j < 1000; j++) {
counter.increment();
}
});
threads.add(t);
t.start();
}
for (Thread t : threads) {
t.join();
}
System.out.println("最终计数: " + counter.count); // 期望100000
}
}
BUG分析
- 问题:程序运行多次会得到不同的结果,通常小于100000
- 原因:
count++由读取、修改、写入三个步骤组成,多个线程同时执行时会产生数据竞争 - 解决方案:使用
AtomicInteger、synchronized或Lock保证原子性
修复方法
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet();
}
案例3:死锁(Deadlock)
代码示例
public class DeadlockExample {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
// 线程1:先获取lock1,再获取lock2
Thread thread1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("Thread1: 获得了lock1");
try { Thread.sleep(100); } catch (Exception e) {}
synchronized (lock2) {
System.out.println("Thread1: 获得了lock2");
}
}
});
// 线程2:先获取lock2,再获取lock1
Thread thread2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("Thread2: 获得了lock2");
try { Thread.sleep(100); } catch (Exception e) {}
synchronized (lock1) {
System.out.println("Thread2: 获得了lock1");
}
}
});
thread1.start();
thread2.start();
}
}
BUG分析
- 问题:程序运行后可能永远卡住,两个线程互相持有对方需要的锁
- 原因:锁的竞争顺序不一致,形成循环等待
- 解决方案:固定锁的获取顺序,或使用
tryLock搭配超时
修复方法
// 方法1:固定锁顺序
// 方法2:使用ReentrantLock的tryLock
ReentrantLock lock1 = new ReentrantLock();
ReentrantLock lock2 = new ReentrantLock();
if (lock1.tryLock()) {
try {
if (lock2.tryLock()) {
try { /* 业务逻辑 */ } finally { lock2.unlock(); }
}
} finally { lock1.unlock(); }
}
案例4:线程安全性问题(ArrayList)
代码示例
public class ArrayListThreadSafety {
private static ArrayList<Integer> list = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
List<Integer> task1 = new ArrayList<>();
List<Integer> task2 = new ArrayList<>();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
list.add(i);
task1.add(i);
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
list.add(i);
task2.add(i);
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("list大小: " + list.size()); // 期望20000
System.out.println("task1大小: " + task1.size() + ", task2大小: " + task2.size());
System.out.println("两线程成功添加总数: " + (task1.size() + task2.size()));
}
}
BUG分析
- 问题:list.size()可能小于20000,甚至出现数组越界异常
- 原因:
ArrayList不是线程安全的,多个线程同时修改内部数组结构时会导致数据丢失或位置错乱 - 解决方案:使用
CopyOnWriteArrayList、Vector或Collections.synchronizedList()
修复方法
private static List<Integer> list =
Collections.synchronizedList(new ArrayList<>());
// 或
private static CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
案例5:单例模式双重检查锁问题
代码示例
public class SingletonDCL {
private static SingletonDCL instance;
public static SingletonDCL getInstance() {
if (instance == null) { // 第一次检查
synchronized (SingletonDCL.class) {
if (instance == null) { // 第二次检查
instance = new SingletonDCL(); // 非原子操作
}
}
}
return instance;
}
private SingletonDCL() {}
}
BUG分析
- 问题:可能返回一个尚未完全初始化的实例
- 原因:
instance = new SingletonDCL()包含三步(分配内存、初始化对象、赋值),JVM可能重排序导致先赋值再初始化 - 解决方案:使用
volatile关键字或静态内部类方式
修复方法
private static volatile SingletonDCL instance; // 添加volatile
这些案例展示了Java并发编程中的典型问题,在实际开发中,建议遵循以下原则:
- 使用线程安全的数据结构和工具类
- 注意可见性、原子性和有序性
- 设计无锁方案或合理的锁策略
- 使用并发工具类如
CountDownLatch、Semaphore等
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播