避免线程安全问题的核心思路是:要么让共享数据“只读”,要么让对共享数据的访问“互斥”,要么干脆“不共享”。下面从原理到实践系统说明。
当多个线程同时访问共享数据,且至少有一个线程在修改数据,而程序又没有正确的同步机制时,就可能发生:
线程封闭(Thread Confinement)
ThreadLocalpublic void process() {
int count = 0; // 局部变量,线程安全
}
✅ 优点:最简单、最高效
❌ 缺点:不适合需要共享状态的场景
一旦创建,就不能修改
finalpublic final class User {
private final String name;
private final int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
}
✅ 不可变对象天然线程安全
当必须修改共享数据时,使用锁保证同一时间只有一个线程访问
synchronized (lock) {
count++;
}
或使用 ReentrantLock:
Lock lock = new ReentrantLock();
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
✅ 适合复杂操作
❌ 性能开销、可能死锁
优先使用 JDK 提供的线程安全工具
| 场景 | 推荐 |
|---|---|
| 计数 | AtomicInteger |
| 集合 | ConcurrentHashMap |
| 队列 | BlockingQueue |
| 状态标记 | volatile |
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet();
✅ 内部使用 CAS,性能优于锁
synchronized (lock) {
// 只放必须同步的代码
}
volatilevolatile 不能保证原子性,只保证:
✅ 适合:
❌ 不适合:
i++ 这种复合操作synchronized 就安全”ArrayList)避免线程安全问题 = 避免“多线程 + 可变 + 共享”同时存在
如果你愿意,我可以:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。