重入鎖和讀寫鎖

   在java多線程中,我們知道可以用synchronize關鍵字來實現線程間的同步互斥工作,還有更加優秀的機制去實現同步互斥工作,Lock對象。重入鎖和讀寫鎖,他們具有比synchronize更加強大的功能,並且具有嗅探鎖定,多路分支等功能。
一、ReentrantLock(重入鎖)(詳見JDK-API)

public class UseReentrantLock {
	
	private Lock lock = new ReentrantLock();
	
	public void method1(){
		try {
			lock.lock();
			System.out.println("當前線程:" + Thread.currentThread().getName() + "進入method1..");
			Thread.sleep(1000);
			System.out.println("當前線程:" + Thread.currentThread().getName() + "退出method1..");
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			
			lock.unlock();
		}
	}
	
	public void method2(){
		try {
			lock.lock();
			System.out.println("當前線程:" + Thread.currentThread().getName() + "進入method2..");
			Thread.sleep(2000);
			System.out.println("當前線程:" + Thread.currentThread().getName() + "退出method2..");
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			
			lock.unlock();
		}
	}
	
	public static void main(String[] args) {

		final UseReentrantLock ur = new UseReentrantLock();
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				ur.method1();
				ur.method2();
			}
		}, "t1");

		t1.start();
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//System.out.println(ur.lock.getQueueLength());
	}
}

二、鎖的等待與通知
  在使用synchronize的時候,如果需要多線程之間進行協作工作,則需要Object的wait()和notify(),notifyAll( )方法進行配合工作。那麼同樣,我們在使用Lock的時候,可以使用一個新的等待通知類,它就是Condition,這個Condition一定是針對具體某一把鎖的。也就是在只有鎖的基礎上纔會產生Condition。

public class UseCondition {

	private Lock lock = new ReentrantLock();
	private Condition condition = lock.newCondition();
	
	public void method1(){
		try {
			lock.lock();
			System.out.println("當前線程:" + Thread.currentThread().getName() + "進入等待狀態..");
			Thread.sleep(3000);
			System.out.println("當前線程:" + Thread.currentThread().getName() + "釋放鎖..");
			condition.await();	// Object wait
			System.out.println("當前線程:" + Thread.currentThread().getName() +"繼續執行...");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void method2(){
		try {
			lock.lock();
			System.out.println("當前線程:" + Thread.currentThread().getName() + "進入..");
			Thread.sleep(3000);
			System.out.println("當前線程:" + Thread.currentThread().getName() + "發出喚醒..");
			condition.signal();		//Object notify
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public static void main(String[] args) {
		
		final UseCondition uc = new UseCondition();
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				uc.method1();
			}
		}, "t1");
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				uc.method2();
			}
		}, "t2");
		t1.start();

		t2.start();
	}
	
}

三、多Condition
  我們可以通過一個Lock對象產生多個Condition進行多線程間的交互,非常的靈活。可以使得部分需要喚醒的線程喚醒,其他線程則繼續等待通知。

public class UseManyCondition {

	private ReentrantLock lock = new ReentrantLock();
	private Condition c1 = lock.newCondition();
	private Condition c2 = lock.newCondition();
	
	public void m1(){
		try {
			lock.lock();
			System.out.println("當前線程:" +Thread.currentThread().getName() + "進入方法m1等待..");
			c1.await();
			System.out.println("當前線程:" +Thread.currentThread().getName() + "方法m1繼續..");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void m2(){
		try {
			lock.lock();
			System.out.println("當前線程:" +Thread.currentThread().getName() + "進入方法m2等待..");
			c1.await();
			System.out.println("當前線程:" +Thread.currentThread().getName() + "方法m2繼續..");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void m3(){
		try {
			lock.lock();
			System.out.println("當前線程:" +Thread.currentThread().getName() + "進入方法m3等待..");
			c2.await();
			System.out.println("當前線程:" +Thread.currentThread().getName() + "方法m3繼續..");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void m4(){
		try {
			lock.lock();
			System.out.println("當前線程:" +Thread.currentThread().getName() + "喚醒..");
			c1.signalAll();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void m5(){
		try {
			lock.lock();
			System.out.println("當前線程:" +Thread.currentThread().getName() + "喚醒..");
			c2.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public static void main(String[] args) {
		
		
		final UseManyCondition umc = new UseManyCondition();
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				umc.m1();
			}
		},"t1");
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				umc.m2();
			}
		},"t2");
		Thread t3 = new Thread(new Runnable() {
			@Override
			public void run() {
				umc.m3();
			}
		},"t3");
		Thread t4 = new Thread(new Runnable() {
			@Override
			public void run() {
				umc.m4();
			}
		},"t4");
		Thread t5 = new Thread(new Runnable() {
			@Override
			public void run() {
				umc.m5();
			}
		},"t5");
		
		t1.start();	// c1
		t2.start();	// c1
		t3.start();	// c2
		

		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		t4.start();	// c1
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		t5.start();	// c2
		
	}
	

四 . Lock / Condition其他方法和用法
   1.公平鎖和非公平鎖: Lock lock = new ReentrantLock ( boolean isFair);
   lock的用法:
     tryLock():嘗試獲得鎖,獲得結果用true/false返回.
      tryLock():在給定的時間內嘗試獲得鎖,獲得結果用true/false返回.
      isFair():是否是公平鎖
      isLocked():是否鎖定
      getHoldCount():查詢當前線程保持此鎖的個數,也就是調用lock()的次數
      lockInterruptibly:優先響應中斷的鎖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章