开篇
最近在学习GUI并发编程,本篇文章为相关整理的第1篇。
并发编程基础概念
- 并发 vs 并行
// 串行示例(顺序执行)
void makeTea() {
washTeapot(); // 洗茶具
fetchWater(); // 打水
boilWater(); // 烧水
pourTea(); // 冲茶
}
// 并行示例(多线程)
new Thread(() -> { washTeapot(); }).start(); // 并行洗茶具
new Thread(() -> {
fetchWater();
boilWater();
pourTea();
}).start();
- 并发编程价值
- 资源利用率:多核CPU负载均衡
- 响应速度:耗时任务异步处理(如Web服务器)
- 任务拆分:分段下载/生产者消费者模型
线程安全的三大挑战
上下文切换开销
优化方案:
// 无锁编程示例(分段处理)
IntStream.range(0, 4).parallel().forEach(i -> {
processSegment(data, i); // 每个线程处理不同数据段
});
// CAS原子操作
AtomicInteger count = new AtomicInteger();
count.incrementAndGet(); // 无锁线程安全
死锁(Deadlock)
经典死锁案例:
// HAIR_A 和 HAIR_B 两个锁对象
synchronized(HAIR_A) {
Thread.sleep(50);
synchronized(HAIR_B) { ... } // 等待B锁
}
synchronized(HAIR_B) {
synchronized(HAIR_A) { ... } // 等待A锁
}
🔍 检测工具:jconsole 监控线程状态
线程不安全(Race Condition)
// 典型不安全操作
public class UnSafeThread {
private static int num = 0;
public static void inCreate() { num++; } // 非原子操作
public static void main(String[] args) {
// 10个线程各执行100次累加
IntStream.range(0, 10).forEach(i -> new Thread(() -> {
IntStream.range(0, 100).forEach(j -> inCreate());
}).start());
// 预期结果1000,实际输出<1000
}
}
线程核心机制
线程生命周期
线程正确中断方式
// 推荐方案:状态标志位
class SafeInterrupt implements Runnable {
private volatile boolean running = true;
public void run() {
while (running) {
// 执行任务
}
}
void cancel() { running = false; } // 安全终止
}
守护线程(Daemon Thread)
Thread daemonThread = new Thread(() -> {
while (true) { /* 后台任务 */ }
});
daemonThread.setDaemon(true); // 设置为守护线程
daemonThread.start();
⚠️ 注意:JVM在所有用户线程结束时自动终止守护线程
线程安全实现方案
synchronized 同步锁
volatile 关键字
private volatile boolean flag; // 保证可见性
// 适用场景:状态标志位
public void shutdown() {
flag = true; // 所有线程立即可见
}
💡 特点:可见性、禁止指令重排,但不保证原子性
原子类(Atomic Classes)
AtomicInteger counter = new AtomicInteger();
// 线程安全自增
counter.getAndIncrement();
// CAS底层实现
public final int getAndIncrement() {
return U.getAndAddInt(this, VALUE, 1);
}
最佳实践总结
- 锁粒度控制:尽量缩小同步代码块范围
- 避免嵌套锁:预防死锁(Lock Ordering)
- 线程复用:使用线程池(ThreadPoolExecutor)
- 并发工具优先:ConcurrentHashMap > Collections.synchronizedMap()
- 状态不可变:final修饰共享变量
📊 性能对比:原子操作 > 无锁编程 > 轻量锁 > 重量锁
注
以上便是我本篇博客的所有内容了,感谢阅读!
希望您能有所收获~