[問題] thread會將值存在register中不寫回?

看板C_and_CPP作者 (Ar藤)時間5年前 (2018/10/14 18:46), 5年前編輯推噓4(4021)
留言25則, 8人參與, 5年前最新討論串1/1
這個問題是出自"程式設計師的自我修養"這一本書 裡面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

10/14 19:10, 5年前 , 1F
看不太懂,x應該是同一塊記憶體,怎會有flush的問題
10/14 19:10, 1F

10/14 20:14, 5年前 , 2F
恩...應該 compiler 優化有問題才會像你說的這樣啊?有
10/14 20:14, 2F

10/14 20:14, 5年前 , 3F
沒有前後文?
10/14 20:14, 3F

10/14 20:30, 5年前 , 4F
他後面有提到 volatile 和 memory barrier, page 29
10/14 20:30, 4F
※ 編輯: Arton0306 (36.227.78.148), 10/14/2018 20:36:06

10/14 20:38, 5年前 , 5F
我說flush是指寫出去到memory的意思
10/14 20:38, 5F

10/14 20:40, 5年前 , 6F
29頁那個cpu自行換序的問題 我試過真的會發生
10/14 20:40, 6F

10/14 20:40, 5年前 , 7F
但28頁這個我沒遇過
10/14 20:40, 7F

10/14 20:46, 5年前 , 8F
再看一次 好像真的如同L大說的 這段是在講compiler的問
10/14 20:46, 8F

10/14 20:48, 5年前 , 9F
題 所以compiler看到mutex夾住的要小心 應該是這意思@@
10/14 20:48, 9F

10/14 20:54, 5年前 , 10F
我原本以為它是說code有問題 冏XD
10/14 20:54, 10F

10/14 21:33, 5年前 , 11F
如果是留在暫存器中,也不能算做完x++吧
10/14 21:33, 11F

10/14 21:38, 5年前 , 12F
書上意指lock前就把x值存進暫存器?
10/14 21:38, 12F
我想它這段真的是沒有寫很清楚,以下是我的理解: 它說「落後的編譯器技術已經無法滿足日益增長的並行需求,很多看似無錯的程式碼 在最佳化和並行面前又產生了麻煩,最簡單的例子…(就是我上面寫的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

10/14 23:38, 5年前 , 13F
唉,連記憶體到CPU暫存器的時間也要省
10/14 23:38, 13F

10/15 01:19, 5年前 , 14F
存取暫存器的時間遠小於記憶體啊 XD
10/15 01:19, 14F

10/15 02:18, 5年前 , 15F
現在的C/C++有規範不同thread之間的memory model
10/15 02:18, 15F

10/15 02:28, 5年前 , 16F
以std::mutex來說 unlock "synchronizes-with"下一個lock
10/15 02:28, 16F

10/15 02:28, 5年前 , 17F
unlock前的side effects必須讓lock後的code看到
10/15 02:28, 17F

10/15 02:28, 5年前 , 18F
如果編譯器沒有把x的值寫回記憶體的話就是做錯了
10/15 02:28, 18F

10/15 13:05, 5年前 , 19F
c++ 11以後要follow sequential consistency.
10/15 13:05, 19F
感謝 原來後來加進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

10/16 09:44, 5年前 , 20F
seq_cst是atomic operation之間預設才有
10/16 09:44, 20F

10/16 09:44, 5年前 , 21F
像上面那種bool isStop兩個threads同時寫還是UB
10/16 09:44, 21F

10/16 09:45, 5年前 , 22F
除非你有用mutex等東西讓兩個讀寫有"happens-before"的關係
10/16 09:45, 22F

10/16 22:12, 5年前 , 23F
用volatile應該就會讓compiler每次都會寫回memory了吧
10/16 22:12, 23F

10/17 10:47, 5年前 , 24F
照標準volatile和thread之間的synchronization是沒有關係的
10/17 10:47, 24F

10/17 10:48, 5年前 , 25F
而且volatile也不一定是atomic access
10/17 10:48, 25F
我發現我原本寫的thread 1的while (isStop)寫錯了 改了while (!isStop) 才對 我上面的例子只有2個thread,只有thread2才會去寫isStop ※ 編輯: Arton0306 (220.136.4.208), 12/07/2018 01:38:57
文章代碼(AID): #1RmnvfpQ (C_and_CPP)