Java面试题之多线程 锁的分类
在Java中,多线程编程是一个重要的主题,而锁是实现线程安全的关键机制。锁的分类可以从多个角度进行分析,以下是一些常见的分类方式:
内置锁(监视器锁):Java中的每个对象都有一个内置锁,使用synchronized
关键字来实现。内置锁是不可重入的,意味着同一个线程在持有锁的情况下再次请求该锁会导致死锁。
显式锁:使用java.util.concurrent.locks
包中的Lock
接口及其实现类(如ReentrantLock
、ReadWriteLock
等)。显式锁提供了更灵活的锁机制,比如可以尝试获取锁、可中断的锁等。
粗粒度锁:锁住较大范围的资源,通常会导致较高的线程竞争和较低的并发性能。例如,锁住整个对象或整个方法。
细粒度锁:锁住较小范围的资源,通常可以提高并发性能。例如,锁住对象的某个字段或某个方法的局部区域。
独占锁(排他锁):同一时间只能被一个线程持有,其他线程必须等待。例如,ReentrantLock
的lock()
方法。
共享锁:多个线程可以同时持有锁,适用于读操作。例如,ReadWriteLock
中的读锁。
可重入锁:同一个线程可以多次获取同一把锁而不会导致死锁。例如,ReentrantLock
是可重入的。
不可重入锁:同一个线程在持有锁的情况下再次请求该锁会导致死锁。例如,使用synchronized
关键字的内置锁在某些情况下可能表现为不可重入。
公平锁:按照线程请求锁的顺序来获取锁,避免线程饥饿。例如,ReentrantLock
可以通过构造函数设置为公平锁。
非公平锁:不保证线程获取锁的顺序,可能导致某些线程长时间得不到锁。大多数情况下,Java的内置锁和ReentrantLock
的默认行为是非公平的。
偏向锁:在没有竞争的情况下,锁会偏向于第一个获得锁的线程,减少获取锁的开销。
轻量级锁:在竞争不激烈的情况下,使用自旋锁来减少上下文切换的开销。
重量级锁:在竞争激烈的情况下,使用操作系统的互斥量,性能较低。
了解锁的分类及其特性对于编写高效的多线程程序至关重要。在实际开发中,选择合适的锁类型可以有效提高程序的并发性能和响应速度。