字節(jié)跳動(dòng)一面:i++是線程安全的嗎?
閱讀本文大概需要 4 分鐘。
# Thread的本地內(nèi)存
每個(gè)Thread都擁有自己的線程存儲(chǔ)空間
Thread何時(shí)同步本地存儲(chǔ)空間的數(shù)據(jù)到主存是不確定的
# 例子

不用 volatile
使用 volatile
每次修改volatile變量都會(huì)同步到主存中
每次讀取volatile變量的值都強(qiáng)制從主存讀取最新的值(強(qiáng)制JVM不可優(yōu)化volatile變量,如JVM優(yōu)化后變量讀取會(huì)使用cpu緩存而不從主存中讀取)
線程 A 中寫(xiě)入 volatile 變量之前可見(jiàn)的變量, 在線程 B 中讀取該 volatile 變
量以后, 線程 B 對(duì)其他在 A 中的可見(jiàn)變量也可見(jiàn). 換句話說(shuō), 寫(xiě) volatile 類似于退出同步塊, 而讀取 volatile 類似于進(jìn)入同步塊
# 注意
public class VolatileTest {? ?private static volatile int count = 0;? ?private static final int times = Integer.MAX_VALUE;? ?public static void main(String[] args) {? ? ? ?long curTime = System.nanoTime();? ? ? ?Thread decThread = new DecThread();? ? ? ?decThread.start();? ? ? ?// 使用run()來(lái)運(yùn)行結(jié)果為0,原因是單線程執(zhí)行不會(huì)有線程安全問(wèn)題? ? ? ?// new DecThread().run();? ? ? ?System.out.println(Start thread: + Thread.currentThread() + i++);? ? ? ?for (int i = 0; i < times; i++) {? ? ? ? ? ?count++;? ? ? ?}? ? ? ?System.out.println(End thread: + Thread.currentThread() + i--);? ? ? ?// 等待decThread結(jié)束? ? ? ?while (decThread.isAlive());? ? ? ?long duration = System.nanoTime() - curTime;? ? ? ?System.out.println(Result: + count);? ? ? ?System.out.format(Duration: %.2fs\n, duration / 1.0e9);? ?}? ?private static class DecThread extends Thread {? ? ? ?@Override? ? ? ?public void run() {? ? ? ? ? ?System.out.println(Start thread: + Thread.currentThread() + i--);? ? ? ? ? ?for (int i = 0; i < times; i++) {? ? ? ? ? ? ? ?count--;? ? ? ? ? ?}? ? ? ? ? ?System.out.println(End thread: + Thread.currentThread() + i--);? ? ? ?}? ?}}
Start thread: Thread[main,5,main] i++ Start thread: Thread[Thread-0,5,main] i-- End thread: Thread[main,5,main] i-- End thread: Thread[Thread-0,5,main] i-- Result: -460370604 Duration: 67.37s
void?f1()?{?i++;?}
void?f1();Code:0:?aload_01:?dup2:?getfield?#2;?//Field?i:I5:?iconst_16:?iadd7:?putfield?#2;?//Field?i:I10:?return
Thread1?????????????Thread2r1?=?i;?????????????r3?=?i;???????????????r2?=?r1?+?1;????????r4?=?r3?+?1;i?=?r2;?????????????i?=?r4;
# 線程同步問(wèn)題的解決
package com.qunar.atomicinteger;import java.util.concurrent.atomic.AtomicInteger;/*** @author zhenwei.liu created on 2013 13-9-2 下午10:18* @version $Id$*/public class SafeTest {? ?private static AtomicInteger count = new AtomicInteger(0);? ?private static final int times = Integer.MAX_VALUE;? ?public static void main(String[] args) {? ? ? ?long curTime = System.nanoTime();? ? ? ?Thread decThread = new DecThread();? ? ? ?decThread.start();? ? ? ?// 使用run()來(lái)運(yùn)行結(jié)果為0,原因是單線程執(zhí)行不會(huì)有線程安全問(wèn)題? ? ? ?// new DecThread().run();? ? ? ?System.out.println(Start thread: + Thread.currentThread() + i++);? ? ? ?for (int i = 0; i < times; i++) {? ? ? ? ? ?count.incrementAndGet();? ? ? ?}? ? ? ?// 等待decThread結(jié)束? ? ? ?while (decThread.isAlive());? ? ? ?long duration = System.nanoTime() - curTime;? ? ? ?System.out.println(Result: + count);? ? ? ?System.out.format(Duration: %.2f\n, duration / 1.0e9);? ?}? ?private static class DecThread extends Thread {? ? ? ?? ? ? ?public void run() {? ? ? ? ? ?System.out.println(Start thread: + Thread.currentThread() + i--);? ? ? ? ? ?for (int i = 0; i < times; i++) {? ? ? ? ? ? ? ?count.decrementAndGet();? ? ? ? ? ?}? ? ? ? ? ?System.out.println(End thread: + Thread.currentThread() + i--);? ? ? ?}? ?}}
Start thread: Thread[main,5,main] i++ Start thread: Thread[Thread-0,5,main] i-- End thread: Thread[Thread-0,5,main] i-- Result: 0 Duration: 105.15
# 結(jié)論
推薦閱讀:
如何一眼識(shí)別螞蟻集團(tuán)身價(jià)千萬(wàn)的阿里人
Spring Boot+JWT+Shiro+MyBatisPlus 實(shí)現(xiàn) RESTful 快速開(kāi)發(fā)后端腳手架
微信掃描二維碼,關(guān)注我的公眾號(hào)
朕已閱?
評(píng)論
圖片
表情

