线程锁是用来实现同步机制的,前面讲到过使用synchronized关键字来实现同步。
使用这个关键字实现的同步块有一些缺点:
(1)锁只有一种类型
(2)线程得到锁或者阻塞
(3)不能实现很好的并发
为了解决如上的各种问题,后来又提出了一种更为复杂的锁 - 线程锁。
线程锁可以在几个方面进行提升:
(1)添加不同类型的锁,如读取锁和写入锁(主要实现类为ReentrantReadWriteLock类)
(2)对锁的阻塞没有限制,即可以在一个方法中上锁,在另外一个方法中解锁。
(3)如果线程得不到锁,比如锁由另外一个线程持有,就允许该线程后退或继续执行,或者做其他事情 - 使用类中提供的tryLock()方法
(4)允许线程尝试取锁,并可以在超过等待时间后放弃。
1、下面来认识一下一个简单的线程锁 - Lock锁。
public interface Lock {
/* 获取锁。如果锁不获取,在获得锁之前,该线程将一直处于休眠状态。
*/
void lock();
/* 如果当前线程未被中断,则获取锁。如果锁可用,则获取锁,并立即返回。
如果锁不可用,则该线程将一直处于休眠状态,直到:
(1) 锁由当前线程获得;或者
(2)其他某个线程中断当前线程。
注意:如果当前线程,
(1)在进入此方法时已经设置了该线程的中断状态;或者
(2)在获取锁时被中断,并且支持对锁获取的中断,
则将抛出 InterruptedException,并清除当前线程的已中断状态。
*/
void lockInterruptibly() throws InterruptedException;
/* 仅在调用时,锁为空闲状态才获取该锁。
如果锁可用,则获取锁,并立即返回值 true。
如果锁不可用,则此方法将立即返回值 false。
此方法的典型使用语句如下:
Lock lock = ...;
if (lock.tryLock()) {
try {
// manipulate protected state
} finally {
lock.unlock();
}
} else {
// perform alternative actions
}
此用法可确保如果获取了锁,则会释放锁,如果未获取锁,则不会试图将其释放。
*/
boolean tryLock();
/* 如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。
如果锁可用,则此方法将立即返回值 true。
如果锁不可用,该线程将一直处于休眠状态:直到下面三种情况出现
(1)锁由当前线程获得;或者
(2)其他某个线程中断当前线程,并且支持对锁获取的中断;或者
(3)已超过指定的等待时间
如果获得了锁,则返回值 true。
注意:如果当前线程:
(1)在进入此方法时已经设置了该线程的中断状态;或者
(2)在获取锁时被中断,并且支持对锁获取的中断,
则将抛出 InterruptedException,并会清除当前线程的已中断状态。
如果超过了指定的等待时间,则将返回值 false。
如果 time 小于等于 0,该方法将完全不等待。
time为等待时长,unit为time参数的时间单位
*/
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
/* 释放锁。
*/
void unlock();
/* 返回绑定到此 Lock 实例的新 Condition 实例。
在等待条件前,锁必须由当前线程保持。调用 Condition.await() 将在等待前以原子方式释放锁,
并在等待返回前重新获取锁。
*/
Condition newCondition();
}
Lock
实现提供了比使用 synchronized
方法和语句可获得的更广泛的锁定操作。
锁是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资源的独占访问。一次只能有一个线程获得锁,对共享资源的所有访问都需要首先获得锁。不过,某些锁可能允许对共享资源并发访问,如 ReadWriteLock
的读取锁。
synchronized
方法或语句的使用提供了对与每个对象相关的隐式监视器锁的访问,但却强制所有锁获取和释放均要出现在一个块结构中,Lock
接口的实现允许锁在不同的作用范围内获取和释放,并允许以任何顺序获取和释放多个锁。不使用块结构锁就失去了使用 synchronized
方法和语句时会出现的锁自动释放功能。而Lock需要自己调用unlock()手动释放锁,否则会产生死锁。锁定和取消锁定出现在不同作用范围中时,必须谨慎地确保保持锁定时所执行的所有代码用 try-finally 或 try-catch 加以保护,以确保在必要时释放锁。
2、Lock的实现类ReentrantLock
首先说一下ReentrantLock的内置类Sync,而Sync 是extends AbstractQueuedSynchronizer