初步使用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();並確保在使用中鎖住的對象實例是獨有的即可.