可見性、原子性和有序性講解

前傳

咱們的CPU、內存、I/O設備都在不斷迭代,不斷朝着更快的方向的努力。可是有一個核心矛盾一直存在,就是三者速度的差別。CPU和內存的速度差別能夠形容爲:CPU是天上一天,內存是地上一年;內存和I/0設備的速度差別就更大了,內存是天上一天,I/O設備是地上十年。緩存

可見性

緩存致使的可見性問題

在單核時代,全部線程都是在同一CPU上執行的,全部線程都是操做同一個CPU的緩存,一個線程對緩存的寫,對另外一個線程來講必定是可見的。例以下圖中,線程A和線程B都是操做同一個CPU裏面的緩存,因此線程A更新了變量V的值,那麼線程B以後再訪問變量V,獲得的必定是V的最新值。 線程

一個線程對共享變量的修改,另一個線程可以馬上看到,稱爲可見性。

多核時代,每顆CPU都有本身的緩存,這時CPU緩存與內存的數據一致性就沒那麼容易解決了,當多個線程在不一樣的CPU上執行時,這些線程操做的是不一樣的CPU緩存。 下圖中,線程A操做的是CPU-1上的緩存,而線程B操做的是CPU-2上的緩存,很明顯,這個時候線程A對變量V的操做對應線程B而言就不具備可見性了。 3d

直覺告訴咱們應該是2000000,但實際狀況多是1000000到2000000之間的任意一個值。cdn

假設線程A和線程B同時執行,那麼第一次都會講count=0讀到各自的CPU緩存裏,執行完count+=1以後,各自CPU緩存裏的值都是1,同時寫入內存後,咱們會發現內存中是1,而不是咱們期待的2。以後因爲各自的CPU緩存裏都有count的值(1),兩個線程都是基於CPU緩存裏的count值來計算的,因此致使最終中count的值要小於2000000,。這就是緩存可見性的問題。blog

若是循環的次數更大,咱們會發現效果更明顯,最終的count值差值越大,緣由是兩個線程不時同時啓動的,有一個時差。內存

原子性

count+=1,至少須要三條CPU指令。it

指令1:首先,須要把count變量從內存加載到CPU寄存器。 指令2:以後,在寄存器中執行+1操做。 指令3:最後,將結果寫入內存(緩存機制致使的多是寫入CPU緩存而不是內存) 若是線程A在指令1執行以後作線程切換,線程A和線程B按照下圖的序列執行,那麼咱們發現兩個線程都執行了count+=1操做,獲得的結果不是咱們指望的2,而是1.io

咱們潛意識裏面以爲 count+=1 這個操做是一個不可分割,就像原子同樣,線程的切換能夠發生在count+=1以前,也能夠發生在count+=1以後,可是不會發生在中間。class

咱們把一個或者多個操做在CPU執行的過程當中不被中斷的特性稱爲原子性。變量

有序性

有序性實例

相關文章
相關標籤/搜索