一 . 概述
在JDK5之前,我们都需要使用synchronized来完成内置锁的实现同步效果,Synchronized的操作力度过大,因而出现了一个替代的产品ReentrantLock(可重入锁).
二 .可重入锁的基本使用
在这里我们还是使用前面的计数操作完成演示.
public class ReenTest { // 创建一个可重入锁 private static Lock lock = new ReentrantLock(); private int count = 0; private void add() { lock.lock(); try { count++; } finally { lock.unlock(); } } public static void main(String[] args) throws Exception { ReenTest test = new ReenTest(); Thread t1 = new Thread(()->{ for(int x = 0; x< 10000 ;x++) { test.add(); } } ) ; Thread t2 = new Thread(()->{ for(int x = 0; x< 10000 ;x++) { test.add(); } } ); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("最终的结果count:"+test.count); } }
我们看到可重入锁的使用非常简单,核心方法一个是lock(),另外一个就是unlock()方法.
注意 : 我们的unlock一定要放置在finally之中,保证锁一定是释放的,否则可能会出现死锁.
三 , 可重入锁实现的四个特点
[1]阻塞式
可重入锁一样是阻塞式的,也就是说,进入临界资源的线程只有一个.
[2]可重入性
这个比较简单了,名字就知道了.
[3]公平性
我们首先观察可重入锁的构造方法
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
这个构造函数指明锁是否是公平锁.,我们通过构造函数来指明.默认是非公平锁.
那么什么是公平和非公平呢?我们知道所有的线程被阻塞到AQS的队列之中,实际上这些线程也是有先来后到的.
所谓公平,就是保证这个先来后到.
所谓不公平,就是前一个线程完成之后,所有线程再次抢夺一个资源.
四 .总结
我们使用可重入锁基本能替代掉synchronized关键词,相比较而言,我们还能实现更加灵活的操作.
缺点也是有的,我们需要使用大量的代码去控制lock的使用.