看板 C_and_CPP 關於我們 聯絡資訊
這個問題是出自"程式設計師的自我修養"這一本書 裡面28頁陳述了一個問題 x = 0; Thread1 Thread2 lock(); lock(); x++; x++; unlock(); unlock(); 書上說可能thread1做完x++時,這個x=1的值還留在register中還沒寫回, 之後換thread2跑完,很久之後thread1才把此值寫回,最後x的值是1 但書上這個例子看起來就是一般multithread用mutex鎖住一段code的寫法, 目前也沒看過這種寫法發生錯誤 請問這個情況什麼時候會發生? 還是說平常在用的unlock會自動把register中的值flush出去? 我把28頁照片放上來 https://photos.app.goo.gl/QYG5LffdJLUC9PfA8 (特別查了一下著作權法,放個一頁應該是沒什麼問題@@) 著作權法第五十二條規定:「 為報導、評論、教學、研究或其他正當目的之必要,在合理範圍內, 得引用已公開發表之著作。」 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 36.227.78.148 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1539513961.A.CDA.html
stupid0319: 看不太懂,x應該是同一塊記憶體,怎會有flush的問題 10/14 19:10
Lipraxde: 恩...應該 compiler 優化有問題才會像你說的這樣啊?有 10/14 20:14
Lipraxde: 沒有前後文? 10/14 20:14
descent: 他後面有提到 volatile 和 memory barrier, page 29 10/14 20:30
※ 編輯: Arton0306 (36.227.78.148), 10/14/2018 20:36:06
Arton0306: 我說flush是指寫出去到memory的意思 10/14 20:38
Arton0306: 29頁那個cpu自行換序的問題 我試過真的會發生 10/14 20:40
Arton0306: 但28頁這個我沒遇過 10/14 20:40
Arton0306: 再看一次 好像真的如同L大說的 這段是在講compiler的問 10/14 20:46
Arton0306: 題 所以compiler看到mutex夾住的要小心 應該是這意思@@ 10/14 20:48
Arton0306: 我原本以為它是說code有問題 冏XD 10/14 20:54
stupid0319: 如果是留在暫存器中,也不能算做完x++吧 10/14 21:33
stupid0319: 書上意指lock前就把x值存進暫存器? 10/14 21:38
我想它這段真的是沒有寫很清楚,以下是我的理解: 它說「落後的編譯器技術已經無法滿足日益增長的並行需求,很多看似無錯的程式碼 在最佳化和並行面前又產生了麻煩,最簡單的例子…(就是我上面寫的code)」 也就是它舉了一個compiler最佳化出bug的例子, 在它的例子中 x+1的值留在register中,不是lock前就存進暫存器, 而是因為有可能之後會再用到,這樣比較快 singlethread是可以這麼做, 但在multithread的情況下,這樣的最佳化是compiler的bug 而它28頁最下方和29頁的例子是code真的有問題 compiler不可能解決 2個例子擺在一起容易誤會 ※ 編輯: Arton0306 (36.227.78.148), 10/14/2018 23:09:24
stupid0319: 唉,連記憶體到CPU暫存器的時間也要省 10/14 23:38
Bencrie: 存取暫存器的時間遠小於記憶體啊 XD 10/15 01:19
PkmX: 現在的C/C++有規範不同thread之間的memory model 10/15 02:18
PkmX: 以std::mutex來說 unlock "synchronizes-with"下一個lock 10/15 02:28
PkmX: unlock前的side effects必須讓lock後的code看到 10/15 02:28
PkmX: 如果編譯器沒有把x的值寫回記憶體的話就是做錯了 10/15 02:28
steve1012: c++ 11以後要follow sequential consistency. 10/15 13:05
感謝 原來後來加進standard了 想到一段以前寫過的code bool isStop = false; // global var thread 1 thread 2 while (!isStop) { do something... do something isStop = true } 也就是thread1 重複做某件事 直到thread2設定了isStop的flag 例如用在gui取消/中斷某個耗時的計算 現在回想起來 isStop沒有用lock包起來是否有問題?? 如果加上volatile 而沒有lock 這樣是否安全? ※ 編輯: Arton0306 (36.227.78.148), 10/16/2018 01:59:34
PkmX: seq_cst是atomic operation之間預設才有 10/16 09:44
PkmX: 像上面那種bool isStop兩個threads同時寫還是UB 10/16 09:44
PkmX: 除非你有用mutex等東西讓兩個讀寫有"happens-before"的關係 10/16 09:45
jun0325: 用volatile應該就會讓compiler每次都會寫回memory了吧 10/16 22:12
PkmX: 照標準volatile和thread之間的synchronization是沒有關係的 10/17 10:47
PkmX: 而且volatile也不一定是atomic access 10/17 10:48
我發現我原本寫的thread 1的while (isStop)寫錯了 改了while (!isStop) 才對 我上面的例子只有2個thread,只有thread2才會去寫isStop ※ 編輯: Arton0306 (220.136.4.208), 12/07/2018 01:38:57