順序一致性

  1. 來自Leslie Lamport的經典論文《How to Make a Multiprocessor Computer That Correctly Executes Multiprocess Programs》:

" Consider a computer composed of several such processors accessing a common memory. The customary approach to designing and proving the correctness of multiprocess algorithms for such a computer assumes that the following condition is satisfied : the result of any execution is the same as if the operations of all the processors were executed in some sequential order, and the operations of each individula processor appear in this sequence in the order specified by its program. A multiprocessor satisfying this condition will be called sequentially consistent." --- LESLIE LAMPORT

【案例1】只有兩個進程的互斥協議

process 1 :
  a = 1; //1
  if (b == 0) {//2
    // 進入臨界區域
    a = 0;
    // 退出臨界區域
  }else {
    // 執行其他操作
  }
process 2 :  
  b = 1;//3
  if (a == 0) {//4
    // 進入臨界區域
    b = 0;
    // 退出臨界區域
  }else {
    // 執行其他操作
  }

分析:
如果process 1先執行if(b==0)或者process 2先執行if (a==0),即存在一個進程的執行順序和定義順序不一致(可能是由于編譯器或者處理器的優化措施導致),就有可能導致兩個進程同時進入臨界區域,從出現錯誤。因此必須要求:從單個進程來看,每個處理器的執行順序必須和定義順序一致,從而就禁止了編譯器或者處理器的優化措施。

從上述要求1,可以得出下面兩個有用的推論:

  1. 從全局的角度,每個CPU看到的其他CPU的寫操作都是按照相同的順序執行的,看到的最終執行的視圖是一致的;
  2. 單個CPU對共享變量的寫操作馬上對其他CPU可見
    證明:假設單個CPU對共享變量的寫操作不是馬上對其他CPU可見的,即在當前線程把寫過的數據緩存在本地內存中,且還沒有刷新到主內存之前,這個寫操作僅對當前線程可見;從其他線程的角度來觀察,會認為這個寫操作根本還沒有被當前線程執行。只有當前線程把本地內存中寫過的數據刷新到主內存之后,這個寫操作才能對其他線程可見。在這種情況下,當前線程和其它線程看到的操作執行順序將不一致,從而違反推論1。

【案例2】假設每個內存模塊都有多個端口,一個端口服務一個處理器。假設ab被存儲在不同的內存模塊中,現在發生了以下事件:

  1. 處理器1向內存塊1上專用于服務處理器1的端口發送a=1的請求。但是內存塊1正忙于執行其他處理器的操作;

  2. 處理器1向內存塊2上專用于服務處理器1的端口發送fetch b的請求。內存2是空閑的,則開始執行,進入臨界區;

  3. 處理器2向內存塊2上專用于服務處理器2的端口發送b=1的請求。這個請求在處理器1的fetch b完成后開始執行;

4)處理器2向內存塊1上專用于服務處理器2的端口發送fetch a的請求。此時內存塊1還忙于執行其他處理器的操作;

現在有兩個操作等著被內存塊2執行,如果處理器2的fetch a請求先被執行,則同時有兩個進程進入臨界區域。進而有第二個要求:

單個內存塊必須按照先來先服務的規則來處理來自多個處理器的所有請求。

  1. 來自Java1.7語言規范里的[https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5](Java Memory Model)里的定義:

    A set of actions is sequentially consistent if all actions occur in a total order (the execution order) that is consistent with program order, and furthermore, each read r of a variable v sees the value written by the write w to v such that:

    • w comes before r in the execution order, and
    • there is no other write w' such that w comes before w' and w' comes before r in the execution order.

    Sequential consistency is a very strong guarantee that is made about visibility and ordering in an execution of a program. Within a sequentially consistent execution, there is a total order over all individual actions (such as reads and writes) which is consistent with the order of the program, and each individual action is atomic and is immediately visible to every thread.

    If a program has no data races, then all executions of the program will appear to be sequentially consistent.

    Sequential consistency and/or freedom from data races still allows errors arising from groups of operations that need to be perceived atomically and are not.

    If we were to use sequential consistency as our memory model, many of the compiler and processor optimizations that we have discussed would be illegal.

【參考資料】

  1. https://www.microsoft.com/en-us/research/wp-content/uploads/2016/12/How-to-Make-a-Multiprocessor-Computer-That-Correctly-Executes-Multiprocess-Programs.pdf
  2. 《聊聊高并發(三十三)Java內存模型那些事(一)從一致性(Consistency)的角度理解Java內存模型》http://blog.csdn.net/iter_zc/article/details/41943387
  3. 《深入理解Java內存模型(三)——順序一致性》http://www.infoq.com/cn/articles/java-memory-model-3
  4. 《為什么程序員需要關心順序一致性(Sequential Consistency)而不是Cache一致性(Cache Coherence?)》
    http://www.infoq.com/cn/articles/java-memory-model-3
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容