1. 程式人生 > >Java多執行緒-53-ReentrantLock類-互斥鎖

Java多執行緒-53-ReentrantLock類-互斥鎖

前面文章末尾,我們提到wait會釋放鎖,而sleep不會釋放鎖。那麼什麼是鎖,鎖就是把執行緒鎖住。也就是執行緒能被鎖住,當然還有釋放鎖。這篇來了解下ReentrantLock類,中文的意思就是互斥鎖。主要學習這個類的lock()獲取鎖和unlock()釋放鎖。

互斥鎖程式碼舉例

我們先來看程式碼,然後來解釋。

package thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLock_Demo {

	public static void main(String[] args) {
		Printer3 p = new Printer3();
		
		new Thread() {
			public void run() {
				while(true) {
					try {
						p.print1();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
        
		new Thread() {
			public void run() {
				while(true) {
					try {
						p.print2();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
		
		new Thread() {
			public void run() {
				while(true) {
					try {
						p.print3();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
	}

}

class Printer3 {
	private int flag = 1;
	private ReentrantLock r = new ReentrantLock(); 
	private Condition c1 = r.newCondition();
	private Condition c2 = r.newCondition();
	private Condition c3 = r.newCondition();
	public void print1() throws InterruptedException {
		r.lock();
			if(flag != 1) {
				c1.await();      // C1進入等待狀態
			}
			System.out.print("跟");
			System.out.print("我");
			System.out.print("一");
			System.out.print("起");
			System.out.println("念");
			flag = 2;
			c2.signal();        // c1等待 喚醒c2
		r.unlock();
	}
	
	public void print2() throws InterruptedException {
		r.lock();
			if(flag != 2) {
				c2.await();
			}
			System.out.print("做");
			System.out.print("測");
			System.out.print("試");
			System.out.print("死");
			System.out.print("路");
			System.out.print("一");
			System.out.println("條");
			flag = 3;
			c3.signal(); 			// c2等待,喚醒c3 
		r.unlock();
	}
	
	public void print3() throws InterruptedException {
		r.lock();
			if(flag != 3) {
				c3.await();
			}
			System.out.print("信");
			System.out.print("才");
			System.out.print("怪");
			System.out.println("呢");
			flag = 1;
			c1.signal();            // c3等待,喚醒c1
		r.unlock();
	}
}

執行結果和前面使用同步鎖是一樣的。第一點不同,由前面while語句改成了if語句判斷。第二個不同,由互斥鎖物件r呼叫lock和unlock方法來替代原來的synchronized。第三點不同,三個執行緒之間,喚醒都是很明確的,執行緒1等待喚醒的是執行緒2,執行緒2等待喚醒執行緒3,執行緒3等待喚醒的執行緒1. 這裡使用了互斥鎖的成員方法newCondition(),裡面Condition類有await()方法就是相當於前面學習的wait方法,signal()方法就是前面的notify()方法。互斥鎖比前面的同步程式碼塊功能要強大很多。