在 Java 中,锁的分类和实现方式多种多样,主要可以分为以下几类:

1. 乐观锁与悲观锁

  • 乐观锁:认为数据在并发操作时不会被修改,因此不加锁,只在更新时检查数据是否被修改。常见的实现方式是 CAS(Compare and Swap),如 AtomicInteger、AtomicLong 等原子类。
  • 悲观锁:认为数据在并发操作时一定会被修改,因此在操作前加锁。常见的实现方式是 synchronized 关键字和 ReentrantLock。

2. 可重入锁与非可重入锁

  • 可重入锁:允许同一个线程多次获取同一把锁,如 synchronized 和 ReentrantLock。
  • 非可重入锁:不允许同一个线程多次获取同一把锁,必须等待锁释放后才能再次获取

3. 公平锁与非公平锁

  • 公平锁:按照线程申请锁的顺序分配锁,保证先到先得,如 ReentrantLock 的公平模式。
  • 非公平锁:不保证申请锁的顺序,可能导致某些线程长时间无法获取锁,但性能较高。

4. 自旋锁与阻塞锁

  • 自旋锁:线程在获取锁失败时不会立即阻塞,而是通过循环(自旋)尝试获取锁,适用于锁竞争不激烈的场景。
  • 阻塞锁:线程在获取锁失败时会进入阻塞状态,等待锁释放后被唤醒。

5. 互斥锁与读写锁

  • 互斥锁:同一时刻只允许一个线程访问共享资源,如 synchronized 和 ReentrantLock。
  • 读写锁:允许多个读线程同时访问共享资源,但写线程独占资源,如 ReentrantReadWriteLock。

6. 锁升级

  • 偏向锁:适用于只有一个线程访问同步代码块的场景,减少锁的开销。
  • 轻量级锁:当偏向锁被其他线程访问时,升级为轻量级锁,通过自旋尝试获取锁。
  • 重量级锁:当自旋次数达到一定阈值后,升级为重量级锁,线程进入阻塞状态。

7. 分段锁

  • 将锁的粒度细化,对不同的数据段使用不同的锁,减少锁竞争,如 ConcurrentHashMap 的实现。

总结

Java 中的锁可以根据不同的特性进行分类,如乐观锁与悲观锁、可重入锁与非可重入锁、公平锁与非公平锁等。常见的锁实现包括 synchronized、ReentrantLock、ReentrantReadWriteLock 以及原子类(如 AtomicInteger)。选择合适的锁可以提高并发性能并避免死锁等问题。


高旭
40 声望3 粉丝