ReentrantLock是JDK唯一实现了Lock接口的类
lock()
是平常使用得最多的一个方法,就是用来获取锁。如果锁已被其他线程获取,则进行等待。
由于在前面讲到如果采用Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁。因此一般来说,使用Lock必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生。
实例
各自独立的Lock对象
@Testpublic void testLock1() {// 两个线程的lock对象是彼此独立,没有任何关系,没有起到锁的作用new Thread() {@Overridepublic void run() {Lock lock = new ReentrantLock();String tName=Thread.currentThread().getName();System.out.println(tName+"还没有锁,开始主动获取锁......");lock.lock();// 主动获取锁System.out.println(tName+"获取到锁!");try {int n = 1 / 0;System.out.println(n);for (int i = 0; i < 10; i++) {System.out.println(tName+":" + i);}} catch (Exception e) {System.out.println(tName+"出错了!!!");}finally {//lock.unlock();}}}.start();new Thread() {@Overridepublic void run() {Lock lock = new ReentrantLock();String tName=Thread.currentThread().getName();System.out.println(tName+"还没有锁,开始主动获取锁......");lock.lock();// 主动获取锁,此时获取不到锁,因为线程1出错了,lock()不会主动释放锁,线程1又没有释放锁,所以就死锁了。System.out.println(tName+"tName获取到锁!");for (int i = 0; i < 10; i++) {System.out.println(tName+":" + i);}}}.start();}
运行结果:
Thread-0还没有锁,开始主动获取锁......
Thread-0获取到锁!
Thread-0出错了!!!
Thread-1还没有锁,开始主动获取锁......
Thread-1tName获取到锁!
Thread-1:0
Thread-1:1
Thread-1:2
Thread-1:3
Thread-1:4
Thread-1:5
Thread-1:6
Thread-1:7
Thread-1:8
Thread-1:9
锁对象是同一个
两个线程的锁对象是同一个,当获取锁的线程没有释放锁的时候,就产生了死锁,其他线程只能无止尽地等待
@Testpublic void testLock2() {//两个线程的锁对象是同一个,当获取锁的线程没有释放锁的时候,就产生了死锁,其他线程只能无止尽地等待Lock lock = new ReentrantLock();new Thread() {@Overridepublic void run() {String tName=Thread.currentThread().getName();System.out.println(tName+"还没有锁,开始主动获取锁......");lock.lock();// 主动获取锁System.out.println(tName+"获取到锁!");try {int n = 1 / 0;System.out.println(n);for (int i = 0; i < 10; i++) {System.out.println(tName+":" + i);}} catch (Exception e) {System.out.println(tName+"出错了!!!");}finally {}}}.start();new Thread() {@Overridepublic void run() {String tName=Thread.currentThread().getName();System.out.println(tName+"还没有锁,开始主动获取锁......");lock.lock();// 主动获取锁,此时获取不到锁,因为之前出错了,lock()不会主动释放锁,线程又没有释放锁,所以就死锁了。System.out.println(tName+"tName获取到锁!");for (int i = 0; i < 10; i++) {System.out.println(tName+":" + i);}}}.start();}
Thread-0还没有锁,开始主动获取锁......
Thread-0获取到锁!
Thread-0出错了!!!
Thread-1还没有锁,开始主动获取锁......
释放锁
两个线程的锁对象是同一个,当获取锁的线程没有释放锁的时候,就产生了死锁,其他线程只能无止尽地等待
在try-finally里不管是顺利执行完,还是出错,都要主动释放锁,则其他线程就能获取到
@Testpublic void testLock3() {//两个线程的锁对象是同一个,当获取锁的线程没有释放锁的时候,就产生了死锁,其他线程只能无止尽地等待//在try-finally里不管是顺利执行完,还是出错,都要主动释放锁,则其他线程就能获取到Lock lock = new ReentrantLock();new Thread() {@Overridepublic void run() {String tName=Thread.currentThread().getName();System.out.println(tName+"还没有锁,开始主动获取锁......");lock.lock();// 主动获取锁System.out.println(tName+"获取到锁!");try {int n = 1 / 0;System.out.println(n);for (int i = 0; i < 10; i++) {System.out.println(tName+":" + i);}} catch (Exception e) {System.out.println(tName+"出错了!!!");}finally {System.out.println(tName+"释放锁!!");lock.unlock();}}}.start();new Thread() {@Overridepublic void run() {String tName=Thread.currentThread().getName();System.out.println(tName+"还没有锁,开始主动获取锁......");lock.lock();// 主动获取锁,此时获取不到锁,因为之前出错了,lock()不会主动释放锁,线程又没有释放锁,所以就死锁了。System.out.println(tName+"tName获取到锁!");for (int i = 0; i < 10; i++) {System.out.println(tName+":" + i);}}}.start();}
Thread-0还没有锁,开始主动获取锁......
Thread-0获取到锁!
Thread-0出错了!!!
Thread-0释放锁!!
Thread-1还没有锁,开始主动获取锁......
Thread-1tName获取到锁!
Thread-1:0
Thread-1:1
Thread-1:2
Thread-1:3
Thread-1:4
Thread-1:5
Thread-1:6
Thread-1:7
Thread-1:8
Thread-1:9