您的位置:首页 >Java多线程数据安全解决方案
发布于2026-01-25 阅读(0)
扫一扫,手机访问
i++不是原子操作,因其被拆分为读取、计算、写回三步,多线程下易发生竞态导致结果错误;volatile仅保可见性不保原子性;synchronized、AtomicInteger、ThreadLocal等是常用线程安全方案。

i++ 为什么不是原子操作?因为 i++ 实际拆成三步:读取 i 的值 → 计算 i + 1 → 写回新值。多个线程可能同时读到相同旧值,各自加 1 后写回,导致最终只加了一次。
常见现象是:10 个线程各执行 1000 次 i++,结果远小于 10000;或者日志中出现重复 ID、计数跳变、ConcurrentModificationException 等。
volatile 能保证可见性,但不能解决复合操作的原子性问题(如 i++、list.add())synchronized 锁住临界区是最直接的控制方式它通过 JVM 的 monitor 机制确保同一时刻只有一个线程能进入被保护的代码块或方法,适合逻辑清晰、争用不激烈的场景。
public class Counter {
private int count = 0;
public synchronized void increment() {
count++; // 这里是原子的
}
public synchronized int getCount() {
return count;
}
}
synchronized 锁的是当前实例(this),静态方法锁的是类对象(Counter.class)String 或常量池对象(如 "lock")作锁,容易被外部误用导致锁失效或死锁java.util.concurrent 包里的工具类更适合高并发场景当需要频繁读写、或对性能敏感时,ReentrantLock、AtomicInteger、ConcurrentHashMap 等比 synchronized 更灵活高效。
AtomicInteger 用 CAS(Compare-And-Swap)实现无锁原子更新,适用于简单计数:counter.incrementAndGet()ReentrantLock 支持可中断、超时、公平锁等特性,但需手动 lock()/unlock(),忘记 unlock() 会导致死锁ConcurrentHashMap 不是“线程安全的 HashMap”,而是分段锁 + CAS 的高性能实现,get() 完全无锁,put() 只锁对应桶ArrayList 或 HashMap 包裹在 synchronized 块里使用——它们本身不提供迭代器一致性保障,仍可能抛 ConcurrentModificationException它为每个线程提供独立副本,彻底规避竞争。典型用途是保存用户上下文、数据库连接、格式化器(如 SimpleDateFormat)等非线程安全对象。
private static final ThreadLocalDATE_FORMAT = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
get() 都返回当前线程专属实例,无需同步remove(),尤其在线程池场景下,否则会造成内存泄漏(ThreadLocalMap 中的 key 是弱引用,value 不是)ThreadLocal 值,需显式使用 InheritableThreadLocalsynchronized 补丁。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9