synchronized块比方法更灵活因锁粒度可控,仅保护共享变量操作;volatile不保证原子性,不能替代synchronized;concurrenthashmap采用细粒度锁,性能优于hashtable;reentrantlock需手动释放,支持中断与超时。

为什么synchronized块比方法更灵活
因为锁的粒度可以精确控制,避免整个方法被阻塞。比如只对共享变量的读写加锁,不影响方法内其他非共享逻辑执行。
常见错误是把整个方法用 synchronized 修饰,但实际只需要保护几行更新 counter 的代码。这会导致不必要的线程等待,尤其在方法体较长、含I/O或计算时。
- 锁对象必须是所有线程可见且一致的,推荐用
private final Object lock = new Object(); - 不要用
this或类对象(如MyClass.class)作锁,除非明确需要实例级或类级独占 - 嵌套同步块要小心死锁,确保加锁顺序一致
volatile 能不能替代 synchronized
不能。它只保证变量的可见性和禁止指令重排序,不提供原子性。
典型误用:用 volatile int count 做自增——count++ 是读-改-写三步操作,volatile 无法阻止两个线程同时读到旧值再各自+1。
立即学习“Java免费学习笔记(深入)”;
- 适合场景:状态标志位,如
volatile boolean running - 不适合场景:复合操作(
++、--、+=)、依赖当前值的判断(如“如果为0才设为1”) - 配合
AtomicInteger等原子类使用更安全
ConcurrentHashMap 和 Hashtable 的关键区别
核心在于锁策略:ConcurrentHashMap 默认分段锁(JDK 8+ 改为 CAS + synchronized 细粒度桶锁),而 Hashtable 对整个表加 synchronized 方法锁。
这意味着多线程读写不同 key 时,ConcurrentHashMap 几乎无竞争,Hashtable 却会互相阻塞。
-
ConcurrentHashMap不允许nullkey 或 value;Hashtable也不允许,但行为更严格(直接抛NullPointerException) -
ConcurrentHashMap的迭代器弱一致性,可容忍并发修改;Hashtable的Enumeration是 fail-fast 的 - 高并发写场景下,
ConcurrentHashMap性能通常高出数倍
为什么 ReentrantLock 比 synchronized 更难用但有时必须用
因为它把锁的获取、释放、中断、超时等细节暴露出来,给了你更多控制权,也意味着更多出错可能。
最常踩的坑是忘记在 finally 块里调用 unlock(),导致锁永远不释放。而 synchronized 是 JVM 自动管理的,不可能漏掉。
- 必须配对使用:
lock.lock()→try→finally { lock.unlock(); } - 支持公平锁(构造时传
true),但会降低吞吐量,一般不用 - 可响应中断(
lockInterruptibly())、支持超时(tryLock(1, TimeUnit.SECONDS)),这是synchronized做不到的









