承接上文CPU緩存一致性原理
雙擊QQ.exe從磁盤加載到內存里面,內存里面就會有了一個進程,進程產生的時候會產生一個主線程,就是main方法所在的線程,cpu會找到main開始的地方,把它的指令讀取過來放到程序計數器,把數據放到寄存器,然后ALU開始做計算,一步一步來執行整個程序,這就是普通程序執行的過程。
cpu速度要比內存的速度快100倍,中間有各種各樣的緩存,最常見的是三級緩存,由于它的速度非常快,在執行指令的時候也會有一些優化,比如現在有2條指令,一個是mov指令即從內存中讀取一個數據到某一個寄存器中,第二個指令是把寄存器中的指令數值加1,如果嚴格按照前后寫的效率執行,會發現它的效率比較低;第一條指令從內存中讀數據出來,cpu等待99個時間周期,如果讀完第一個指令之后,才可以執行第二個指令的話,cpu將會有99個空檔期,所以現在的cpu設計是流水線式的設計(采用流水線式后,并沒有加速單條指令的執行,每條指令的操作步驟一個也不能少,只是多條指令的不同操作步驟同時執行,因而從總體上看加快了指令流速度,縮短了程序執行時間),發送一條指令在等待內存數據返回的過程當中,會把后面這條指令執行了即后面的指令跑到前面先執行了,簡單稱為cpu的亂序執行,主要是為了提高效率,在等待費時的指令執行的時候,優先執行后面的指令。
證明cpu亂序執行是存在的
這里有個死循環,每一次循環都會把這4個值(x、y、a、b)設置為0,每一次循環都會起2個線程,第一個線程會執行a=1、x=b,第二個線程會執行b=1、y=a;假設所有的語句都是按照順序執行的,從多線程微觀的角度進行時間順序上的排列組合,你會發現會有各種各樣的組合場景:
比如第一種組合,
第一種組合先執行a=1、x=b,后執行b=1、y=a,得到的結果是x=0、y=1。
這6種排列組合的結果無論如何都不可能得到x=0、y=0的情況即只要按照順序執行,絕對不會出現x=0、y=0。
這是數學上的排列組合,但cpu執行指令的時候未必是按照順序執行的。
出現x=0、y=0的情況比較少見,為什么這么難出現?什么樣的組合下才會出現?
跑了270多萬次才出現了一次x=0、y=0的情況,
這兩種是亂序執行的排列組合,比如第一個場景是線程1先執行x=b、線程2執行y=a,切換到線程1執行a=1,切換到線程2執行b=1,結果是x=0、y=0。
只有這2種場景,2個線程的這2個指令都得顛倒順序才會出現,這種很難出現,不管怎樣,得出一個結論:cpu內部是亂序執行的。
單線程的情況下,2個指令亂了順序執行沒有關系,反正最終的結果是一樣的,但是在多線程的情況下,非常有可能出現你不想看到的情形,比如x=0、y=0的情況,比如在預知中沒有這種情況,但是多線程的情況下,會出現,所以一定會影響整個多線程程序的運行,單線程的程序不會影響。
有了as-if-serial(看上去像序列化的)指令就可以隨便變換順序,只要維持最終一致性即可;單線程的重排序只需要保證最終的一致性,比如a=b、y=1,隨便重排序,只要能保證單線程的最終一致性。
審核編輯:湯梓紅
-
寄存器
+關注
關注
31文章
5336瀏覽量
120231 -
cpu
+關注
關注
68文章
10854瀏覽量
211587 -
指令
+關注
關注
1文章
607瀏覽量
35694 -
緩存
+關注
關注
1文章
239瀏覽量
26672 -
線程
+關注
關注
0文章
504瀏覽量
19675
發布評論請先 登錄
相關推薦
評論