一.限制設計——從結構上說,是利用封裝技術,保證某一時刻只有一個活動訪問某個對象。
方式主要三類,方法限制、線程限制和對象內限制
方法限制:
1.方法內部限制:采用局部變量方式
2.方法間傳遞限制:
a.調用者copy:比如print(p) 可以改為print(new Point(p));
b.接收者copy:Point p=new Point(p.x,p.y);
c.標量參數:print(int x,int y);d.print(p.x,p.y);
線程限制:
1.最簡單的方法是將所有可變對象都放在一個線程內執行
public display(){
new Thread(){
public void run(){//do something here}
}.start()
}
2.線程私有成員變量
最直接的辦法是利用現有類:ThreadLocal.
當然你可以利用Thread.currentThread()自己實現一個類似功能的類,但Thread.currentThread有限制,就是對特定線程的一類。
而ThreadLocal則擺脫了這樣的限制。而且在線程內對ThreadLocal私有變量的讀寫不需要同步。
對象限制:
在前面兩種方法都不能做到對對象的限制訪問時,你就不得不使用鎖。但同時,也可以對對象內部及不同部分的訪問進行結構上的限制。
1.適配器模式
比如 class Point{
public double x;
public double y;
public synchronized double getX(){};
//……
}
采用對象限制的設計方式,會將synchronized 鎖移除到一個其他對象里,這樣就解脫了Point.
like this
class SychPoint {
private final Point point=new Point();
public synchronized double getX(){point.x}
}
class Point{
public double x;
public double y;
public double getX(){};
}
說白了就是采用適配器模式,改變了一下原來類的結構。java.util.Collection framework 里面就是使用這種策略組織起集合類的同步。
2.子類化
將鎖延遲到子類實現,這里將不再羅嗦。
二.同步設計
使用鎖的注意事項
1.有些入口鎖在只有少數線程訪問的情況下,可以很好的工作,開銷并不大。但是當并發量變大,競爭加劇,開銷也變大,系統的性能會隨之下降。大多數線程會把大部分時間浪費在等待上。系統出現了延遲,限制了并發系統的優越性。
2.使用太多的鎖,會增加系統負擔,以及不可料的情況發生,比如死鎖。
3.只用一把鎖來保護一個功能的多個方面會導致資源競爭。
4.長時間持有鎖,會帶來性能問題和異常處理的復雜。
5.有時候加鎖并不一定能保證得到我們想要的結果。
對付以上這些問題,沒有什么最佳策略,大都需要去權衡各個方面的利弊來進行設計。寫多線程的程序,前期的設計比后期維護更為重要。
初期的設計原則,
1.減少同步
a.用戶可以接受陳舊數據,可以拿掉同步,使用volatile
b.用戶在得到非法數據時,只要能得到提示就夠了,可以使用double-check方法。
在不同步時check一次,再在同步狀態在check一次。這么做的意義在于縮小鎖使用范圍,在第一次check不滿足的情況,跳出方法,那么鎖也就用不到了。
c.只對維護狀態部分加鎖:當對象的某個同步方法是比較耗時的操作,那么鎖持有的時間就越長,而僅僅是為了保持一個狀態是,可以采用openCall的方式,減少持有鎖時間。
public sychronized void updateState(){}
public void readFile(){
updateState();//持有鎖
file.read();
}
如上,這種方式的前提是程序不需要同步一個方法中無狀態的部分。如果整個方法都需要鎖,那這種方式就不適用了.
D.能使用同步塊,就不需同步整個方法。
2.分解同步:
分解類
將鎖拆分到輔助類中
分解鎖
如果不愿分解類,可以設計分解鎖
private static Object lock1 = new Object();
private static Object lock2 = new Object();
synchronize(lock1){}
synchronized(lock2){}
在jdk 5.0之后的并發包里,已有可重入鎖供使用。
隔離成員變量
Person的age,income等屬性都需要同步處理,以保證并發修改時,可以設計一些同步的int,Double等類型(util.concurrent已提供類似的類),將鎖交給輔助類去處理。起到隔離作用.