前言
在另一篇文章中Java的synchronized同步介绍了使用synchronized实现同步的特性,Java也可以使用Lock实现同步.本文主要介绍了使用Lock类来实现同步,并进行synchronized和Lock之间的比较.
ReentrantLock是一个类,而synchronized是关键字,ReentrantLock实现了Lock接口.
public class ReentrantLock implements Lock, java.io.Serializable
使用结构
把解锁操作放在finally块中是必要的,这保证了锁一定会被释放掉,否则将会造成死锁.
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
}
finally {
lock.unlock();
}
Lock锁是可重入的
和synchronized一样,Lock锁是可重入的.线程可以重复获得已经持有的锁,锁保持一个持有计数器来跟踪对lock的嵌套调用.
如下的例子,此时线程1可以访问method2(),因为锁是可重入的.但是不能访问method3(),因为持有的是不同的锁.
ReentrantLock lock = new ReentrantLock();
ReentrantLock lock1 = new ReentrantLock();
//method1,锁为lock 正在被线程1访问
public void method1(){
lock.lock();
try {
}
finally {
lock.unlock();
}
}
//method2,锁为lock
public void method2(){
lock.lock();
try {
}
finally {
lock.unlock();
}
}
//method3,锁为lock3 正在被线程2访问
public void method3(){
lock1.lock();
try {
}
finally {
lock.unlock();
}
}
公平锁
ReentrantLock有一个构造器,为true是创建的是公平锁,ReentrantLock的空参构造器创建的是非公平锁.
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
ReentrantLock是使用一个队列来管理公平锁,利用队列的先进先出特性来实现,哪个线程先等待锁,如果当前锁被释放,那么先等待的线程就会先获得锁,
如果是非公平锁那么获得锁的线程是随机的,这个方式有可能造成某些线程拿不到锁,因此是非公平的.
由于要使用队列来管理,因此公平锁相对来讲是效率比较低的.