1. 程式人生 > >java多執行緒之同步鎖(Lock)

java多執行緒之同步鎖(Lock)

      從Java5開始,提供了Lock, Lock提供了比synchronized方法和synchronized程式碼塊更廣泛的鎖定操作,Lock可以實現更靈活的結構,並且支援多個相關的Condition物件(物件監視器)。

      Lock是控制多個執行緒對共享資源進行訪問的工具。通常,鎖提供了對共享資源的獨佔訪問,每次只能有一個執行緒對Lock物件加鎖,執行緒開始訪問共享資源之前應先獲得Lock物件。

示例程式碼:

ReentrantLockTest類:

public class ReentrantLockTest {

	private final ReentrantLock lock = new ReentrantLock();
        //建立10個執行緒
	public void userPrint() {
		for (int i = 0; i < 10; i++) {
			new Thread(new Runnable() {

				public void run() {
					print();
				}
			}).start();
		}
	}

	public void print() {
		lock.lock();
		System.out.println("執行緒" + Thread.currentThread().getName() + "正在使用印表機");
		try {
			Thread.sleep(new Random().nextInt(1000));
			System.out.println("執行緒" + Thread.currentThread().getName() + "資源使用印表機");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
                //獲取等待得到同步鎖的執行緒個數
		System.out.println("還剩 " + lock.getQueueLength() + "人要使用印表機");
		lock.unlock();
	}
}

Main類:

public class Main {
	
	public static void main(String[] args) throws Exception {
        new ReentrantLockTest().userPrint();
}

測試結果:

可以看到我們建立的10個執行緒並沒有同時進來使用印表機方法,而是每次至進入一個執行緒使用印表機。

Lock操作多個Condition物件:

例項程式碼:

ReentrantLockTest類:

public class ReentrantLockTest {

	private final ReentrantLock lock = new ReentrantLock();
	private Condition conditionA = lock.newCondition();
	private Condition conditionB = lock.newCondition();

	public void waitA() {
		lock.lock();
		try {
			System.out.println(Thread.currentThread().getName() + "等待條件");
			conditionA.await();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		lock.unlock();
	}

	public void waitB() {
		lock.lock();
		try {
			System.out.println(Thread.currentThread().getName() + "等待條件(沒有人喚醒我,我將一直等待..)");
			conditionB.await();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		lock.unlock();
	}

	public void signal() throws InterruptedException {
		lock.lock();
		Thread.sleep(1000);
		System.out.println(Thread.currentThread().getName() + "執行完畢,喚醒A");
		conditionA.signal();
		lock.unlock();
	}

	public void condition() throws InterruptedException {
		new Thread(new Runnable() {

			public void run() {
				waitA();
			}
		}).start();
		new Thread(new Runnable() {

			public void run() {
				waitB();
			}
		}).start();
		new Thread(new Runnable() {

			public void run() {
				try {
					signal();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}).start();
	}
}

Mian類:

public class Main {
	
	public static void main(String[] args) throws Exception {
        new ReentrantLockTest().condition();
}

測試結果:

上例中,我們可以看到我們建立了兩個Condition物件,並且啟動了三個執行緒,waitA和waitB方法都在其中一個執行緒執行,但是signal方法只喚醒了持有ConditionA的方法,而另一個waitB方法將一直等待被喚醒。使用Condition可以進行執行緒間的通訊。