像synchronized和ReentrantLock都是可重入锁,可重入性表明了锁的分配机制是基于线程的分配,而不是基于方法调用的分配。
举个简单的例子,当一个线程已经获取到锁,当后续再获取同一个锁,直接获取成功。但获取锁和释放锁必须要成对出现。
可响应中断
当线程因为获取锁而进入阻塞状态,外部是可以中断该线程的,调用方通过捕获InterruptedException可以捕获中断
可设置超时时间
获取锁时,可以指定超时时间,可以通过返回值来判断是否成功获取锁
公平性
提供公平性锁和非公平锁(默认)两种选择。
公平锁,线程将按照他们发出请求的顺序来获取锁,不允许插队;
非公平锁,则允许插队:当一个线程发生获取锁的请求的时刻,如果这个锁是可用的,那这个线程将跳过所在队列里等待线程并获得锁。
考虑这么一种情况:A线程持有锁,B线程请求这个锁,因此B线程被挂起;A线程释放这个锁时,B线程将被唤醒,因此再次尝试获取锁;与此同时,C线程也请求获取这个锁,那么C线程很可能在B线程被完全唤醒之前获得、使用以及释放这个锁。
这是种双赢的局面,B获取锁的时刻(B被唤醒后才能获取锁)并没有推迟,C更早地获取了锁,并且吞吐量也获得了提高。在大多数情况下,非公平锁的性能要高于公平锁的性能。
另外,这个公平性是针对线程而言的,不能依赖此来实现业务上的公平性,应该由开发者自己控制,比如通过FIFO队列来保证公布。
读写锁
允许读锁和写锁分离,读锁与写锁互斥,但是多个读锁可以共存,适用于读频次远大于写频次的场景
丰富的API
提供了多个方法来获取锁相关的信息,可以帮助开发者监控和排查问题
isFair():判断锁是否是公平锁
isLocked():判断锁是否被任何线程获取了
isHeldByCurrentThread():判断锁是否被当前线程获取了
hasQueuedThreads():判断是否有线程在等待该锁