public?class?ThreadTest?{
????private?static?int?threadTotal?=?200;
????private?static?int?clientTotal?=?5000;
????private?static?int?count?=?0;
????public?static?void?main(String[]?args)?throws?InterruptedException?{
????????ExecutorService?executorService?=?Executors.newCachedThreadPool();
????????final?Semaphore?semaphore?=?new?Semaphore(threadTotal);
????????final?CountDownLatch?countDownLatch?=?new?CountDownLatch(clientTotal);
????????for?(int?i?=?0;?i?<?clientTotal;?i++)?{
????????????executorService.execute(()?->?{
????????????????try?{
????????????????????semaphore.acquire();
????????????????????++count;
????????????????????semaphore.release();
????????????????????countDownLatch.countDown();
????????????????}?catch?(InterruptedException?e)?{
????????????????????e.printStackTrace();
????????????????}
????????????});
????????}
????????countDownLatch.await();
????????System.out.println(count);
????????executorService.shutdown();
????}
}這段代碼操作的是一個(gè)static 變量,5000個(gè)線程執(zhí)行了5000次++操作,為什么結(jié)果是線程不安全的
1 回答
已采納

一凡
TA貢獻(xiàn)43條經(jīng)驗(yàn) 獲得超8個(gè)贊
++count的操作實(shí)際是三個(gè)操作
1 cpu從內(nèi)存讀取count
2 cpu內(nèi)部更改count
3 cpu寫入count
多線程的時(shí)候,可能會(huì)有100個(gè)線程同時(shí)讀取的值都是0,那么他們++之后寫回去當(dāng)然就是1,而不是100 。同時(shí)在cpu寫入的時(shí)候,也不是實(shí)時(shí)寫入,而是在cpu高速緩存內(nèi),所以各個(gè)線程內(nèi)的count數(shù)值是不一樣的。
要保證讀寫一致性,需要加入同步的方法來操作。這里只是對(duì)count一個(gè)變量做++運(yùn)算,可以用CAS或者鎖。當(dāng)然JAVA里面的變量屬性 volatile 也是可以保證單個(gè)數(shù)字更新同步的效果。
這里?new
?Semaphore(1); 也可以限制同時(shí)只能有一個(gè)線程進(jìn)入++count操作,也能達(dá)到線程安全的目的。
添加回答
舉報(bào)
0/150
提交
取消