併發: 多線個線程操作相同的資源,保證線程安全,合理使用資源
高併發: 服務能短時間同時處理很多請求,提高程序性能
以下代碼,通過對共享變量進行累加操作,模擬200個線程,客戶端500個請求
private static int threadTotal = 200;
private static int clientTotal = 500;
private static long count = 0;
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
for (int index = 0; index < clientTotal; index++) {
exec.execute(() -> {
try {
semaphore.acquire();
add();
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
exec.shutdown();
log.info("count={}", count);
}
private static void add() {
count++;
}
多次運行程序,會發現每次計算的結果不一致,如果將threadTotal改成1,單個線程執行,多次運行的結果又會一致,
當JAVA程序多條線程執行主內存中的共享變量時,線程與線程之間是如何通信的呢?
假設A線程先執行,會從本地內存A中(抽象模型)取出更新過的共享變量副本刷新到主內存中去,
線程B會去主內存讀取線程A更新過的共享變量
假設上述代碼主內存中共享變量的值爲1,線程A和線程B同時執行,線程A從主內存讀取到的值是1,提取到自己的本地內存中進行+1的操作,將得到的結果2更新到主內存的共享變量
同時線程B,線程A從主內存拿到值爲1的同時,線程B也拿到了1,放入B的本地內存進行+1操作等到2,線程A將結果2更新到主內存的同時,線程B也將結果2更新到主內存,而不是先讀取線程A更新的2之後再重新計算!因此出現了錯誤
解決方案:增加同步的操作
同步的8種操作
lock(鎖定): 作用於主內存的變量,把一個變量標識爲一條線程獨佔狀態
unlock(解鎖):作用於主內存的變量,把一個處於鎖定狀態的變量釋放出來,釋放後的變量纔可以被其他線程鎖定
read(讀取):作用於主內存的變量,把一個變量值從主內存傳輸到線程的工作內存中,以便隨後的load動作使用
load(載入):作用域工作內存的變量,它把read操作從主內存中得到的變量值放入工作內存的變量副本中
user(使用):作用於工作內存的變量,把工作內存中的一個變量值傳遞給執行引擎
assign(賦值):作用於工作內存的變量,它把一個從執行引擎接收到的值賦值給工作內存的變量
store(存儲):作用於工作內存的變量,把工作內存中的一個變量的值傳送到主內存中,以便隨後的write的操作
write(寫入):作用於主內存的變量,它把store操作從工作內存中一個變量的值傳送到主內存的變量中