使用Lock實現多線程同步

Java JDK1.5增加了一個新特性Lock和Conndition接口,Lock對象代替了synchronized同步代碼,將同步代碼快中的鎖對象換成了Condition對象。

一個同步代碼塊只有一個鎖對象對應,如果需要兩個鎖對象的話就需要再加一個同步代碼塊,這樣就容易產生死鎖。

使用了Lock和Condition的話,將鎖對象的wait,notify和notifyAll替換成了Condition對象的await,signal。

這樣就不需要使用多個同步代碼塊而且可以喚醒指定的線程。

以消費者和生產者爲例來演示一下。兩個生產者和兩個消費者,實現交替運行,即生產一個商品就消費一個商品,不能出現連續生產兩個商品或者連續消費兩個商品:


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

class Resources {
	private static Resources mRes = null;
	private String mName;
	private boolean mFlag = false;
	private int mNumber = 1;
	private final ReentrantLock locker = new ReentrantLock();
	private final Condition productCondition = locker.newCondition();
	private final Condition consumerCondition = locker.newCondition();

	private Resources() {
	}

	public static Resources getInstance() {
		if (mRes == null) {
			synchronized (Resources.class) {
				if (mRes == null) {
					mRes = new Resources();
				}
			}
		}

		return mRes;
	}

	public void set(String name) {
		locker.lock();
		
		try{
			// 如果已經生成了一個商品,就等待消費者消費
			while (mFlag) {
				try {
					productCondition.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			mName = name + "--" + mNumber++;
			System.out.println(Thread.currentThread().getName() + "---------生成者: "
					+ mName);
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			mFlag = true;
			consumerCondition.signal();;
		}finally{
			locker.unlock();
		}
	}

	public void out() {
		locker.lock();
		try{
			// 如果消費了商品後,就等待生產者生成
			while (!mFlag) {
				try {
					consumerCondition.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.println(Thread.currentThread().getName() + "消費者: " + mName);
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			mFlag = false;
			productCondition.signal();
		}finally{
			locker.unlock();
		}
	}
}

class Product implements Runnable {
	public void run() {
		Resources res = Resources.getInstance();
		while (true)
			res.set("--------------商品----");
	}
}

class Consumer implements Runnable {
	public void run() {
		Resources res = Resources.getInstance();
		while (true)
			res.out();
	}
}

public class Main {

	public static void main(String[] args) {
		Product p = new Product();
		Consumer c = new Consumer();

		new Thread(p).start();
		new Thread(p).start();
		new Thread(c).start();
		new Thread(c).start();
	}
}


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