java中synchronized與static synchronized 的區別

最近在做一個抽獎活動的計數器,由於抽獎是有人數限制的,所以需要保存抽獎人數;如果保存在數據庫中,那每次進來都得讀寫數據庫,將會造成很大的IO操作,就在內存中保存抽獎人數,用map實與!這裏肯定會存在多線程的,所以map是這樣產生的:

public static Map<String, Long> maxNum = Collections.synchronizedMap(new HashMap<String, Long>());

map中的value表示抽獎人數,後來進行壓測時,用10個線程模擬10萬個用戶,發現最後的結果是,map中的value會出現重複情況,分析原因得知是在對map進行get,put時造成的,這時就在get,put時加了一個鎖,防止其它線程同時防問!代碼如下:

     public  synchronized Long getValue(String draw_type){
		Long currentUserNumber = maxNum.get(draw_type); 
		// 放進全局變量,下一個抽獎的用戶
		maxNum.put(draw_type, currentUserNumber + 1); 
		return currentUserNumber;
	}

此時,原以爲這樣就可以解決問題了,但結果還是一樣!後來加上了static synchronized,問題得到解決;

synchronized是對類的當前實例進行加鎖,防止其他線程同時訪問該類的該實例的所有synchronized塊,注意這裏是“類的當前實例”,類的兩個不同實例就沒有這種約束了。static synchronized恰好就是要控制類的所有實例的訪問了,static synchronized是限制線程同時訪問jvm中該類的所有實例同時訪問對應的代碼塊。

實際上,在類中某方法或某代碼塊中有 synchronized,那麼在生成一個該類實例後,該類也就有一個監視塊,放置線程併發訪問該實例synchronized保護塊,

而static synchronized則是所有該類的實例共用一個監視塊了,這也就是兩個的區別了,也就是synchronized相當於 this.synchronized,而static synchronized相當於:

類名.synchronized.
一個日本作者-結成浩的《java多線程設計模式》有這樣的一個列子:

pulbic class Something(){ 
    public synchronizedvoid isSyncA(){} 
    public synchronizedvoid isSyncB(){} 
    public staticsynchronizedvoid cSyncA(){} 
    public staticsynchronizedvoid cSyncB(){} 

  那麼,加入有Something類的兩個實例x與y,那麼下列組方法何以被1個以上線程同時訪問呢
a. x.isSyncA()與x.isSyncB()  
b. x.isSyncA()與y.isSyncA() 
c. x.cSyncA()與y.cSyncB() 
d. x.isSyncA()與Something.cSyncA() 
  這裏,很清楚的可以判斷:

a,都是對同一個實例的synchronized域訪問,因此不能被同時訪問 

b,是針對不同實例的,因此可以同時被訪問 

c,雖然前後是二個不同的實例,但因爲是static synchronized,所以不同實例之間仍然會被限制,相當於Something.isSyncA()與 Something.isSyncB()了,因此不能被同時訪問。 

那麼,第d呢?,書上的 答案是可以被同時訪問的,答案理由是synchronzied的是實例方法與synchronzied的類方法由於鎖定(lock)不同的原因。 個人分析也就是synchronized 與static synchronized 相當於兩幫派,各自管各自,相互之間就無約束了,可以被同時訪問。目前還不是分清楚java內部設計synchronzied是怎麼樣實現的。
結論:A: synchronized static是某個類的範圍,synchronized static cSync{}防止多個線程同時訪問這個 類中的synchronized static 方法。它可以對類的所有對象實例起作用。B: synchronized 是某實例的範圍,synchronized isSync(){}防止多個線程同時訪問這個實例中的synchronized 方法。


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