Java中的锁机制

一、前言

  • Java中的锁机制是保障多线程环境下资源的安全访问的核心技术。
  • 主要分为隐式锁(synchronized)显式锁(Lock接口实现类)两种类型,同时包含多种锁优化策略和分类。

二、锁的分类与特性

  • 悲观锁 vs 乐观锁
    • 悲观锁:假定资源会被竞争修改,直接加锁(如synchronized、ReentrantLock)。
    • 乐观锁:通过版本号或CAS(Compare And Swap)无锁机制实现(如AtomicInteger),适合读多写少场景。
  • 公平锁 vs 非公平锁
    • 公平锁:按线程申请顺序分配锁(ReentrantLock(true))。
    • 非公平锁:允许插队(synchronized、ReentrantLock(false)),默认情况下性能更高。
  • 可重入锁:同一线程可重复获取同一锁(如synchronized、ReentrantLock),避免死锁。
  • 共享锁 vs 独占锁
    • 共享锁:允许多线程同时读(如ReadWriteLock的读锁)。
    • 独占锁:同一时间仅一个线程持有(如ReentrantLock、synchronized)。

三、synchronized 关键字

  • 实现原理:基于对象头中的 Mark Word 和 Monitor 监视器,通过字节码指令monitorenter和monitorexit控制。
  • 锁升级机制
    • 偏向锁:无竞争时标记线程ID,减少CAS开销。
    • 轻量级锁:通过自旋避免线程阻塞。
    • 重量级锁:竞争激烈时依赖操作系统互斥量(Mutex Lock)。
  • 使用场景:修饰代码块或方法,简单易用但功能有限(如不可中断、不支持超时)。

四、Lock 接口与显式锁

  • ReentrantLock
    • 特性:可重入、支持公平性、可中断、超时获取锁。
    • 示例:
Lock lock = new ReentrantLock();
lock.lock();
try {
    // 临界区代码
} finally {
    lock.unlock();
}
  • ReadWriteLock:读写分离,读锁共享,写锁独占(ReentrantReadWriteLock),提升并发性能。
  • 优势:灵活控制锁的获取与释放,支持多条件变量(Condition)。

五、锁优化技术

  • 自旋锁:竞争时线程执行忙循环(CAS),避免线程切换,适用于短耗时操作。
  • 锁消除:JVM检测无竞争代码(如局部变量操作)自动移除锁。
  • 锁粗化:合并连续加锁/解锁操作,减少性能损耗(如循环内重复加锁)。

六、死锁与解决方案

  • 死锁条件:互斥、请求保持、不可剥夺、循环等待。
  • 避免策略:按顺序获取锁、使用tryLock()设置超时、死锁检测工具(如jstack)。

七、典型应用场景

  • synchronized:简单同步需求,如单例模式、线程安全集合。
  • ReentrantLock:需要复杂控制(如公平性、条件队列)。
  • ReadWriteLock:读多写少场景(如缓存)。
  • CAS/Atomic类:无锁并发(如计数器)。

八、总结

  • Java锁机制的选择需结合性能需求、锁竞争强度及功能复杂度。
  • 基础场景优先使用synchronized。
  • 复杂场景(如高并发、细粒度控制)可选用ReentrantLock或ReadWriteLock,同时通过锁优化技术进一步提升效率。

你可能感兴趣的:(java,java,SE,线程安全,锁,synchronized关键字,Lock)