java synchronized關鍵字學習筆記

synchronized(同步鎖)關鍵字是用來解決共享資源的競爭問題。基本上所有的併發模式在解決線程衝突問題時,都是採用序列化訪問共享資源的方案。這意味着在任意時刻,只允許一個任務訪問共享資源。通常這是通過在代碼前加上一條鎖語句來實現的,這就使得在給定時刻,只允許一個任務可以運行這段代碼。因爲鎖語句產生了一種互相排斥的效果,這種機制常常被稱作互斥量

要控制對共享資源的訪問,得先把它裝進一個對象。然後把所有想訪問這個資源的方法都標記爲synchronized。如果某個任務處於對一個標記爲synchronized的方法的調用中,那麼在這個線程從該方法返回之前,其他所有要調用類中被標記爲synchronized的方法都將處於阻塞狀態

synchronized void f(){}
synchronized void g(){}

所有對象都自動含有單一的鎖(也稱爲監視器)

在使用併發時,將域設置爲private是非常重要的,否則,synchronized關鍵字就不能防止其他任務直接訪問域,這將產生衝突

一個任務可以多次獲得對象的鎖,這表現爲在標記爲synchronized的一個方法中調用另一個標記爲synchronized的方法,甚至可以調用多層。JVM將對調用層數進行計數,直至鎖被完全釋放計數才被置0。

針對每個類,也有一個鎖(作爲類Class對象的一部分),所以synchronized static方法可以在類的範圍內防止對static數據的併發訪問。

每個訪問臨界共享資源的方法都必須被同步,否則它們就不能正確的工作。

public abstract class IntGenerator {
    private volatile boolean canceled=false;
    public abstract int next();
    public void cancel() {canceled=true;}
    public boolean isCanceled() {return canceled;}
}
public class EvenChecker implements Runnable{
    private IntGenerator generator;
    private final int id;
    public EvenChecker(IntGenerator g,int ident) {
    	generator=g;
    	id=ident;
    }
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(!generator.isCanceled()) {
			int val=generator.next();
			if(val%2!=0) {
				System.out.println(val+" is not even");
			}
			generator.cancel();
		}
	}
    public static void test(IntGenerator gp,int count) {
    	System.out.println("Press Control-c to exit");
    	ExecutorService exec=Executors.newCachedThreadPool();
    	for(int i=0;i<count;i++) {
    		exec.execute(new EvenChecker(gp,i));
    	}
    	exec.shutdown();
    }
    public static void test(IntGenerator gp) {
    	test(gp,10);
    }
}

public class EvenGenerator extends IntGenerator{
    private int currentEvenValue=0;
    public synchronized int next() {
    	++currentEvenValue;
    	Thread.yield();
    	++currentEvenValue;
    	return currentEvenValue;
    }
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        EvenChecker.test(new EvenGenerator());
	}

}

若去掉EvenGenertor中修飾next()方法的synchronized關鍵字和讓步語句,將導致多個線程執行混亂。即一個線程並不會執行兩次自加操作。

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