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