多線程關於騰訊筆試題


今天在頭條上看到一道據說是騰訊的筆試題,閑來無事,准備驗證一下!

題目如下:

有一個變量int a=0;兩個線程同時進行+1操作,每個線程加100次,不加鎖,最后a的值是()?

根據我的理解答案不唯一,最大是兩百,最小是2吧。直接上代碼:

 

class MyThread implements Runnable {
    static volatile long i = 0;

    public void run() {
        for (int m = 0; m < 100; m++) {
            i++;
        }
    }
};

public class RunnableTest {
    public static void main(String[] args) throws InterruptedException {
        MyThread mt = new MyThread();

        Thread t1 = new Thread(mt);
        Thread t2 = new Thread(mt);
        t1.start();
        t2.start();
        Thread.sleep(500);
        System.out.println(MyThread.i);
    }
}
結果一臉懵逼,每次都是兩百,我都開始有點懷疑人生了。
考慮之后發現可能是100太小了,樣本空間不夠(偽學霸),吧100改成10000,奇跡出現了
果然大部分時候i的值小於20000.
具體解釋一下原因(復制過來的哈哈):

i++不是原子(就是只由一條指令構成的)操作,也就是說,它不是單獨一條指令,而是3條指令:

 
         

1、從內存中把i的值取出來放到CPU的寄存器中

 
         

2、CPU寄存器的值+1

 
         

3、把CPU寄存器的值寫回內存

假設兩個線程的執行步驟如下: 

 1. 線程A執行第一次i++,取出內存中的i,值為0,存放到寄存器后執行加1,此時CPU1的寄存器中值為1,內存中為0;

 2. 線程B執行第一次i++,取出內存中的i,值為0,存放到寄存器后執行加1,此時CPU2的寄存器中值為1,內存中為0;

 3. 線程A繼續執行完成第99次i++,並把值放回內存,此時CPU1中寄存器的值為99,內存中為99;

 4. 線程B繼續執行第一次i++,將其值放回內存,此時CPU2中的寄存器值為1,內存中為1;

 5. 線程A執行第100次i++,將內存中的值取回CPU1的寄存器,並執行加1,此時CPU1的寄存器中的值為2,內存中為1;

 6. 線程B執行完所有操作,並將其放回內存,此時CPU2的寄存器值為100,內存中為100; 

 7. 線程A執行100次操作的最后一部分,將CPU1中的寄存器值放回內存,內存中值為2;



 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM