同步块保护共享变量的关键是共用同一锁对象,优先使用并发工具类替代手动同步,警惕非原子复合操作,合理使用ThreadLocal并及时清理。
用 synchronized 块保护共享变量的临界区
竞争条件本质是多个线程同时读写同一变量且缺乏同步,导致结果不可预测。最直接的解法是用 synchronized 显式围住所有访问该变量的代码段,确保同一时刻只有一个线程能执行。
注意:锁对象必须是所有线程共用的同一个实例,不能每次 new 一个新对象;静态变量要用 Class.class 或静态 final 对象做锁,避免锁错对象。
- 错误写法:
new Object()作为锁 —— 每次新建对象,锁失效 - 推荐写法:
private static final Object lock = new Object();,然后synchronized(lock) { ... } - 若操作的是实例变量,可用
this,但要确保调用方不会暴露或误用该实例作其他同步
优先使用 java.util.concurrent 包里的线程安全类型
不是所有共享状态都需要手写锁。像计数、队列、Map 这类高频场景,JDK 已提供成熟替代品,比手动同步更简洁、更少出错。
例如:用 AtomicInteger 替代 int 计数器,用 ConcurrentHashMap 替代 HashMap,用 BlockingQueue 实现生产者-消费者通信。
立即学习“Java免费学习笔记(深入)”;