一 简介
ReentrantLock在中文的意思是重入锁与synchronized同步语意一样(具体的区别下面会总结),重入的意思是一个线程可以多次加锁,但是释放锁的时候要释放加锁的次数。ReentrantLock实现就是利用AQS独占模式,内部维护了一个AQS的子类Sync,Sync有两个子类FairSync和NofairSync这两个分别是ReentrantLock的两种锁,公平锁和非公平锁(公平锁与非公平锁介绍)。因为ReentrantLock利用了AQS的独占模式,那么ReentrantLock就可以使用等待队列的相关功能。
二 ReentrantLock的简单使用
如果只是简单使用ReentrantLock,不使用同步队列的话是比较简单。使用方式如下
/**
* ReentrantLock默认是非公平锁 公平锁的创建 private static final ReentrantLock lock = new ReentrantLock(true);
*/
private static final ReentrantLock lock = new ReentrantLock();
public void doSomeThing(){
lock.lock();
try {
//执行业务逻辑,在这里操作可保证线程安全
}finally {
lock.unlock();
}
}
使用方式是比较简单,但是ReentrantLock提供加锁的方式却有不同的方式,具体说明如下
锁定释放只有一个方法unlock()。
三 ReentrantLock等待队列的使用
在ReentrantLock中的Condition提供了Object中的wait(),和notify(),notifyAll()的功能,其中在Condition中的await开头的方法与Object中的wait具有相同的功能,Condition中的signal()和signalAll()分别相当与Object中的notify()和notifyAll(),其中一个lock总可已有多个Condition
下面看代码
private static ReentrantLock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public static void main(String[] args) {
final Thread hh = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
System.out.println(Thread.currentThread() + "等待条件完成");
condition.await();
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread() + "终于等到条件完成了");
lock.unlock();
}
}
});
hh.start();
final Thread qq = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
System.out.println(Thread.currentThread() + "条件完成了");
this.notifyAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
});
qq.start();
}
下面是等待相关的方法说明
唤醒的话是两个方法signal()和singalAll()两个方法,作用的话看方法名就知道了。一个是只唤醒一个,一个是唤醒所有。
四 与synchronized的区别
ReentrantLock和synchronized具有相同的功能,在性能上不会有太大的差别,如果既可以用ReentrantLock也可以用synchronized的话,官方的建议是使用synchronized。因为synchronized在使用的时候比较方便的不用考虑释放锁,而ReentrantLock如果没有释放的话会是其它线程一直处于waiting状态中。但是ReentrantLock也有它特有的功能
1. ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。
2. ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。
3. ReenTrantLock提供了一种能够中断等待锁的线程的机制lock()方法
在同步的时候有上面3需要ReentrantLock的功能可以使用ReenTrantLock,在其他的情况下听官方的。