线程安全指多线程访问共享资源时行为符合预期、结果确定且无数据污染;i++因非原子性(读-改-写三步)、可见性缺失和有序性错乱而不安全;volatile仅解决前两者,synchronized通过Monitor实现原子性、可重入与自动释放;AtomicInteger基于CAS适用于单变量原子操作,但不支持多步协同;根本难点在于识别隐式共享与合理控制锁粒度。
线程安全不是“加了锁就安全”,而是指多个线程同时访问同一对象或变量时,**程序行为始终符合预期,结果确定、无数据污染**。比如一个计数器被 10 个线程各加 100 次,最终必须是 1000 —— 少了,就是不安全;多了,也是不安全。
i++ 不是线程安全的?表面看是一行代码,实际分三步:读取 i → 计算 i+1 → 写回 i。两个线程可能同时读到 i = 5,都算出 6,再都写回去,结果还是 6(本该是 7)。这就是原子性被破坏。
count,但没及时刷到主内存,线程 B 还在用自己缓存的老值volatile 能解决可见性和有序性,但不能修复 i++ 这种复合操作的原子性synchronized 怎么真正起作用?它背后是 JVM 的监视器(Monitor)机制:每个 Java 对象都关联一个 Monitor,monitorenter 和 monitorexit 字节码控制进入/退出。一旦某个线程拿到锁,其他线程只能排队等待。
this 对象ClassName.class
ReentrantLock 更省心)AtomicInteger 替代锁,靠谱吗?靠谱,但只适用于“单一变量的简单操作”。它底层靠 CPU 的 CAS(Compare-And-Swap)指令实现无锁并发,比如 incrementAndGet() 是原子的,不会丢更新。
synchronized
volatile 
int count + count++ 仍是线程不安全的 —— volatile 不保原子性真正难的从来不是“怎么加锁”,而是判断哪些共享状态需要保护、锁的范围是否过宽、有没有隐式共享(比如传入的集合参数被多个线程共用)。线程安全问题往往在压测或上线后才暴露,因为竞态条件依赖于线程调度的偶然性 —— 这也正是它最危险的地方。