本文目录导读:

我来系统地整理Java线程安全的完整知识体系。
线程安全核心概念
1 什么是线程安全
当多个线程访问某个类时,这个类始终表现出正确的行为,就称这个类是线程安全的。
2 线程不安全的根本原因
// 根本原因:多线程操作共享数据
private int count = 0;
public void increment() {
count++; // 不是原子操作:读取-修改-写入
}
三个条件同时发生时必然出现线程安全问题:
- 多线程环境
- 共享资源
- 非原子操作
线程安全实现方式(6大策略)
1 同步机制(Synchronized)
// 1. 同步方法
public synchronized void safeMethod() {
// 线程安全操作
}
// 2. 同步代码块(推荐:粒度更细)
public void safeBlock() {
synchronized(this) {
// 需要同步的操作
}
}
// 3. 静态方法同步(类锁)
public static synchronized void staticSafeMethod() {
// 同步操作
}
// 4. 指定对象锁
private final Object lock = new Object();
public void customLock() {
synchronized(lock) {
// 同步操作
}
}
2 Lock锁机制
import java.util.concurrent.locks.*;
public class LockExample {
private final ReentrantLock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock(); // 必须释放锁
}
}
// 尝试获取锁
public boolean tryIncrement() {
if (lock.tryLock()) {
try {
count++;
return true;
} finally {
lock.unlock();
}
}
return false;
}
// 读写锁
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private Map<String, String> cache = new HashMap<>();
public String get(String key) {
rwLock.readLock().lock();
try {
return cache.get(key);
} finally {
rwLock.readLock().unlock();
}
}
public void put(String key, String value) {
rwLock.writeLock().lock();
try {
cache.put(key, value);
} finally {
rwLock.writeLock().unlock();
}
}
}
3 Volatile关键字
public class VolatileExample {
// volatile保证可见性和禁止指令重排
private volatile boolean flag = false;
private volatile int count = 0;
public void writer() {
count = 10; // 普通写
flag = true; // volatile写,保证前面的写操作对其他线程可见
}
public void reader() {
if (flag) { // volatile读
System.out.println(count); // 一定能看到10
}
}
}
4 原子类(Atomic)
import java.util.concurrent.atomic.*;
public class AtomicExample {
private AtomicInteger count = new AtomicInteger(0);
private AtomicLong longValue = new AtomicLong(0L);
private AtomicBoolean flag = new AtomicBoolean(false);
private AtomicReference<String> ref = new AtomicReference<>("initial");
public void increment() {
count.incrementAndGet(); // 原子自增
count.addAndGet(10); // 原子增加
count.compareAndSet(5, 6); // CAS操作
}
// 复杂对象原子更新
private AtomicReference<User> userRef = new AtomicReference<>();
// 字段原子更新
private AtomicIntegerFieldUpdater<Counter> updater =
AtomicIntegerFieldUpdater.newUpdater(Counter.class, "count");
}
5 并发容器
import java.util.concurrent.*;
public class ConcurrentCollectionExample {
// 1. ConcurrentHashMap - 分段锁
private ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
// 2. CopyOnWriteArrayList - 写时复制
private CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
// 3. BlockingQueue - 阻塞队列
private BlockingQueue<String> queue = new LinkedBlockingQueue<>(100);
// 4. ConcurrentLinkedQueue - 无锁队列
private ConcurrentLinkedQueue<String> concurrentQueue = new ConcurrentLinkedQueue<>();
public void safeOperations() {
// ConcurrentHashMap原子操作
map.putIfAbsent("key", "value"); // 不存在才put
map.computeIfAbsent("key", k -> "new"); // 不存在才计算
map.replace("key", "old", "new"); // 替换操作
// BlockingQueue阻塞操作
try {
queue.put("item"); // 满时阻塞
String item = queue.take(); // 空时阻塞
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
6 ThreadLocal
public class ThreadLocalExample {
// 每个线程维护自己的变量副本
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0; // 初始值
}
};
// Java 8 简化写法
private static ThreadLocal<SimpleDateFormat> dateFormat =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
// 使用示例
public void process() {
Integer value = threadLocal.get(); // 获取当前线程的变量
threadLocal.set(value + 1); // 设置当前线程的变量
threadLocal.remove(); // 使用后清理(避免内存泄漏)
}
// 实际应用:数据库连接管理
private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {
@Override
protected Connection initialValue() {
return DriverManager.getConnection(DB_URL);
}
};
public static Connection getConnection() {
return connectionHolder.get();
}
}
线程安全设计原则
1 不变性(Immutability)
// 不可变对象天然线程安全
public final class ImmutableObject {
private final int id;
private final String name;
private final List<String> tags; // 防御性拷贝
public ImmutableObject(int id, String name, List<String> tags) {
this.id = id;
this.name = name;
this.tags = Collections.unmodifiableList(new ArrayList<>(tags));
}
public int getId() { return id; }
public String getName() { return name; }
public List<String> getTags() {
return tags; // 返回不可修改的视图
}
}
2 线程封闭
// 栈封闭:变量在方法内部,不会被共享
public void stackConfined() {
int localVar = 0; // 每个线程有自己的栈帧
for (int i = 0; i < 100; i++) {
localVar++;
}
}
// ThreadLocal封闭:每个线程自己的副本
private static ThreadLocal<TransactionManager> txManager = new ThreadLocal<>();
3 实例封闭
public class InstanceConfinement {
private final Set<String> set = new HashSet<>(); // 私有成员
private final Object lock = new Object();
public void add(String item) {
synchronized(lock) { // 通过锁保护
set.add(item);
}
}
public boolean contains(String item) {
synchronized(lock) {
return set.contains(item);
}
}
}
线程安全的正确实践
1 类级别线程安全
public class ThreadSafeCounter {
private final AtomicInteger count = new AtomicInteger(0);
private volatile boolean initialized = false;
// 线程安全的初始化
public void init() {
if (!initialized) {
synchronized(this) {
if (!initialized) {
// 双重检查锁定
doInit();
initialized = true;
}
}
}
}
// 线程安全的方法
public int incrementAndGet() {
return count.incrementAndGet();
}
// 复合操作需要同步
public int getAndReset() {
// 保证获取和重置的原子性
synchronized(this) {
int current = count.get();
count.set(0);
return current;
}
}
private void doInit() {
// 初始化代码
}
}
2 发布对象的安全
public class SafePublication {
// 1. 安全发布方式
private static volatile Singleton instance; // volatile确保可见性
// 2. 通过工厂方法安全发布
public static Singleton getInstance() {
if (instance == null) {
synchronized(SafePublication.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
// 3. 通过静态初始化安全发布(推荐)
private static class LazyHolder {
static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance2() {
return LazyHolder.INSTANCE;
}
}
性能优化建议
1 锁优化策略
public class LockOptimization {
// 1. 减少锁持有时间
public void process(List<String> items) {
// 只对必要部分加锁
String result = expensiveComputation(items.get(0));
synchronized(this) {
updateSharedState(result);
}
}
// 2. 减小锁粒度
private final Object lock1 = new Object();
private final Object lock2 = new Object();
private Map<String, String> map1 = new HashMap<>();
private Map<String, String> map2 = new HashMap<>();
public void updateMap1(String key, String value) {
synchronized(lock1) {
map1.put(key, value);
}
}
public void updateMap2(String key, String value) {
synchronized(lock2) {
map2.put(key, value);
}
}
// 3. 锁分离(读写锁)
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
// 4. 锁粗化(避免频繁加解锁)
public void coarsenLock() {
synchronized(this) {
// 多个操作合并
doOperation1();
doOperation2();
doOperation3();
}
}
}
2 选择合适的工具
public class ToolSelection {
// 场景1: 计数器 → 使用AtomicInteger
private final AtomicInteger counter = new AtomicInteger(0);
// 场景2: 共享变量标志位 → 使用volatile
private volatile boolean running = true;
// 场景3: 复杂状态 → 使用Lock或synchronized
private final ReentrantLock lock = new ReentrantLock();
private int state1, state2, state3;
// 场景4: 缓存 → 使用ConcurrentHashMap
private final ConcurrentHashMap<String, CacheEntry> cache =
new ConcurrentHashMap<>();
// 场景5: 生产者消费者 → 使用BlockingQueue
private final BlockingQueue<Task> taskQueue =
new ArrayBlockingQueue<>(1000);
// 场景6: 每个线程独立数据 → 使用ThreadLocal
private final ThreadLocal<UserContext> userContext =
ThreadLocal.withInitial(UserContext::new);
}
常见线程安全问题排查
1 典型问题模式
// 问题1: 非原子检查后执行
public class CheckThenAct {
private Vector<String> vector = new Vector<>();
// 问题代码
public void wrongMethod(String item) {
if (!vector.contains(item)) { // 检查
vector.add(item); // 执行(可能被其他线程干扰)
}
}
// 正确代码
public synchronized void correctMethod(String item) {
if (!vector.contains(item)) {
vector.add(item);
}
}
}
// 问题2: 发布逸出
public class EscapeExample {
private final Map<String, String> map;
// 问题代码:this引用逸出
public EscapeExample() {
// 不应该在构造器中发布this
GlobalRegistry.register(this); // ❌
map = new HashMap<>();
}
// 正确做法:使用工厂方法
private EscapeExample(Map<String, String> map) {
this.map = map;
}
public static EscapeExample create() {
EscapeExample instance = new EscapeExample(new HashMap<>());
GlobalRegistry.register(instance); // ✅ 构造完成后注册
return instance;
}
}
// 问题3: 隐藏的迭代器
public class HiddenIterator {
private final Set<Integer> set = new HashSet<>();
// 问题代码:toString()隐藏了迭代
public String wrongToString() {
return set.toString(); // ❌ 内部迭代,如果在迭代中修改会抛异常
}
// 正确代码
public synchronized String correctToString() {
return set.toString();
}
}
2 调试工具
// 1. 线程转储分析(Jstack)
jstack <pid> > thread_dump.txt
// 2. JVM参数检测
-XX:+UnlockDiagnosticVMOptions
-XX:+PrintConcurrentLocks
// 3. 代码检测
public class DeadlockDetector {
public static void detectDeadlock() {
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
long[] threadIds = threadBean.findDeadlockedThreads();
if (threadIds != null) {
System.out.println("Deadlock detected!");
for (long id : threadIds) {
ThreadInfo info = threadBean.getThreadInfo(id);
System.out.println("Thread: " + info.getThreadName());
}
}
}
}
最佳实践总结
1 线程安全等级
| 等级 | 描述 | 示例 |
|---|---|---|
| 不可变 | 对象创建后不能修改 | String, Integer |
| 绝对线程安全 | 任何环境都安全 | ConcurrentHashMap |
| 相对线程安全 | 单操作安全,复合操作需同步 | Vector, Hashtable |
| 线程兼容 | 通过外部同步实现安全 | ArrayList, HashMap |
| 线程对立 | 即使外部同步也不安全 | (极少见) |
2 选择策略决策树
是否需要共享数据?
├── 否 → 使用ThreadLocal或栈封闭
└── 是 → 数据是否可变?
├── 否 → 使用不可变对象
└── 是 → 是否需要原子性?
├── 否 → 使用volatile
└── 是 → 操作是否简单?
├── 是 → 使用Atomic类
└── 否 → 是否需要读多写少?
├── 是 → 使用ReadWriteLock
└── 否 → 使用synchronized或ReentrantLock
3 编码规范
/** * 线程安全检查清单: * * [ ] 所有共享变量是否被正确保护? * [ ] 复合操作是否原子化? * [ ] 是否存在竞态条件? * [ ] 是否存在可见性问题? * [ ] 是否存在线程封闭的需求? * [ ] 是否选择了合适的同步策略? * [ ] 是否存在死锁风险? * [ ] 锁的粒度是否合适? */
这种系统化的线程安全处理方式,能够帮助你在多线程编程中做出正确的决策,避免常见的并发问题。
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播