java可重入鎖,簡單幾個小案例,測試特性。java
1.嘗試鎖 tryLockide
package com.cn.cfang.ReentrantLock; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Test02 { private Lock lock = new ReentrantLock(); private void m1(){ try{ lock.lock(); for(int i = 0; i < 10; i++){ TimeUnit.SECONDS.sleep(1); System.out.println("m1() method " + i); } }catch(InterruptedException e){ e.printStackTrace(); }finally{ lock.unlock(); } } private void m2(){ boolean isLocked = false; try { //嘗試鎖,若是已被其餘線程鎖住,沒法獲取鎖標記,則返回false //相反,若是獲取鎖標記,則返回true //isLocked = lock.tryLock(); //阻塞嘗試鎖:會阻塞參數表明的時長,再去嘗試獲取鎖標記 //若是超時未獲取,不繼續等待,直接返回false //阻塞嘗試鎖相似於自旋鎖。 isLocked = lock.tryLock(11, TimeUnit.SECONDS); if(isLocked){ System.out.println("method m2 synchronized"); }else{ System.out.println("method m2 unsynchronized"); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(isLocked){ lock.unlock(); } } } public static void main(String[] args) { Test02 t = new Test02(); new Thread(new Runnable() { @Override public void run() { t.m1(); } }).start(); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(new Runnable() { @Override public void run() { t.m2(); } }).start(); } }
2. 可中斷測試
package com.cn.cfang.ReentrantLock; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * ReentrantLock的可打斷性 * * 打斷 : 調用thread.interrupt()方法,可打斷線程阻塞狀態,拋出異常。 * 可嘗試打斷,阻塞等待鎖。 * * 阻塞狀態 :包括普通阻塞狀態,等待隊列,鎖池隊列 * 普通阻塞 : sleep,能夠被打斷。 * 等待隊列 : wait方法調用,也是一種阻塞狀態,不能被打斷,只能等待notify * 鎖池隊列 : 沒法獲取鎖標記。不是全部的鎖池隊列都能被打斷 * ReentrantLock的lock獲取鎖標記的時候,若是未獲取,須要阻塞的去等待鎖標記,沒法被打斷 * ReentrantLock的lockInterruptibly獲取鎖標記的時候,若是未獲取,須要阻塞等待,能夠被打斷 * * @author cfang * 2018年5月4日 下午2:23:41 */ public class Test03 { private Lock lock = new ReentrantLock(); private void m1(){ try { lock.lock(); for(int i = 0; i < 5; i++){ TimeUnit.SECONDS.sleep(1); System.out.println("m1() method " + i); } } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } } private void m2(){ try { lock.lockInterruptibly(); //可嘗試打斷,阻塞等待鎖,能夠被其餘的線程打斷阻塞狀態 System.out.println("m2() method"); } catch (InterruptedException e) { // e.printStackTrace(); }finally{ //可能異常打斷,因此釋放鎖標記必須進行異常處理 try { lock.unlock(); } catch (Exception e2) { e2.printStackTrace(); } } } public static void main(String[] args) { Test03 t = new Test03(); new Thread(new Runnable() { @Override public void run() { t.m1(); } }).start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Thread t2 = new Thread(new Runnable() { @Override public void run() { t.m2(); } }); t2.start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } t2.interrupt(); //打斷線程休眠阻塞等待。非正常結束阻塞狀態的線程,都會拋出異常。 } }
3. 公平鎖 : ReentrantLock可定義公平鎖,多個線程競爭鎖標記的時候,公平鎖會記錄等待時長,當前線程執行結束後,會優先選取等待時長最長的線程,去獲取鎖標記執行。spa
synchronized不具備此特性。線程
1 package com.cn.cfang.ReentrantLock; 2 3 import java.util.concurrent.TimeUnit; 4 import java.util.concurrent.locks.Lock; 5 import java.util.concurrent.locks.ReentrantLock; 6 7 public class Test04 { 8 9 public static void main(String[] args) { 10 TestReentrantlock t = new TestReentrantlock(); 11 new Thread(t).start(); 12 new Thread(t).start(); 13 } 14 15 } 16 17 class TestReentrantlock implements Runnable{ 18 19 private Lock lock = new ReentrantLock(true); //加參數true,表明公平鎖 20 @Override 21 public void run() { 22 for (int i = 0; i < 5; i++) { 23 lock.lock(); 24 try { 25 System.out.println(Thread.currentThread().getName() + " get lock"); 26 }finally{ 27 lock.unlock(); 28 } 29 } 30 } 31 }