初步使用synchronized及心得


假設需要實現以下功能: 設計一個併發程序,併發10個線程,每個線程累加sCount一百萬次,將sCount加到一千萬

public class SyncTest implements Runnable {
	
    public static int sCount = 0;
    
    private static String lock = new String();

    @Override
    public void run() {
        increaseCount();
    }

    private void increaseCount() {
    	/* 打印lock的內存地址 */
    	System.out.println(System.identityHashCode(lock));
    	synchronized (lock) {
            for (int i = 0; i < 1000000; i++) {
            	sCount++;
            }
		}
    }

    public static void main(String[] args) throws InterruptedException {
    	for (int i = 1; i <= 10; i++) {
            new Thread(new SyncTest(), "thread").start();;
		}
        
        Thread.sleep(1000);
    	System.out.println("\n"+sCount);
    }
}

我已線程需要使用到的Runnable是否唯一將實現方法分爲兩類

第一類:Runnable只有1個

1,用synchronized直接修飾increaseCount()方法(實例爲鎖);
2,用synchronized static修飾increaseCount()方法(類爲鎖);
3,用synchronized(this)將increaseCount的for循環包裹住(實例爲鎖);
4,用synchronized(SyncTest.class)將increaseCount的for循環包裹住(類爲鎖);
5,聲明一個對象lock,確保其是唯一的,用synchronized(lock)將increaseCount的for循環包裹住(實例爲鎖);

第二類:Runnable有十個

1,用synchronized static修飾increaseCount()方法(類爲鎖);
2,用synchronized(SyncTest.class)將increaseCount的for循環包裹住(類爲鎖);
3,聲明一個對象lock, 用static修飾lock, 用synchronized(lock)將increaseCount的for循環包裹住(實例爲鎖);

心得

通過以上解決之法可以看出,關鍵點就是不管鎖住的是實例還是類,只要其是唯一的,就可以實現線程同步累加到目標值.
此外一定要注意鎖的影響範圍,比如類鎖會影響到所有用此類爲鎖的實例對象,如無必要,應該縮小作用範圍,比如使用靜態實例作爲鎖.
還要注意在聲明專用鎖對象的時候,儘量不要使用String lock = ""這種常量申明方式,因爲其在全局的常量池裏都是唯一的,
鎖的範圍太大,可能會被使用同樣方式的鎖方法影響,最好使用String lock = new String();並確保在使用中鎖住的對象實例是獨有的即可.

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