程序編譯器是否存在這種機制?

程序執行的時間可能是毫秒級的,在那個微小的時間段里,可能會因為某些外在因素終止程序,在時間軸上,設區間A=[0,x]為程序執行的時間段,a為程序終止運行的時刻,當然a∈A,這種情況下,[0,a]這段時間裡的程序是否被執行過?執行過的操作是否依然有效?程序編譯器是否存在這樣一種機制如同某些大型資料庫的事務般,使得程序要麼完全執行,要麼完全不執行。


話說這個不一定完全符合題主的要求,但不知道題主有沒有聽說過HP有一個神奇的東西叫做NonStop。在NSK(NonStop Kernel)上執行程序就像是一段段地提交事務一樣。這不只是HTM / STM層面上的東西。


很多老手看到這個答案估計第一反應也是 @vczh 的 Software Transaction Memory。其實我說這個問題,還真不是 STM 能解決的。問題就在於,提問者設定的條件太極端。毫秒級,微小,還有未知的外在因素。首先說,DB 的 Transaction 都不見得能解決這樣的問題。DB 的 Transaction 要求文件系統或者 backup storage 在 commit 的時候是可靠的。如果這段時間出問題,transaction 一樣掛掉。恐怕還得人工 set back。

STM 可以用來在底層可靠的時候處理並發。用來處理微秒級的未知 failure,我看不是它設計的目的。


程序是否執行過重要嗎,重要的是影響吧。

所謂的影響無非是——進行了IO操作導致操作泄漏到了CPU以外。比如把數據存進了存儲(包括寄存器、緩存、內存)。

IO的話,有事務化處理的方式,比方說寫文件給文件系統NTFS有Transactional Journal,當然這只是一個特例,其他IO系統也有類似的設計。存儲的話,有事務化內存訪問,除了性能低之外沒什麼特別不好的。

但是,總而言之,這些都和程序沒啥關係啊。程序執行沒執行根本不重要,重要的是相應的數據是否傳遞給了需要的系統。所以,沒人做事務性執行,只做事務性IO。


似乎在新版haswell上intel實現了事務內存,能實現類似樓主的要求,但目前只能寫彙編.聽說C++17會加入事務內存的支持..

所以基本上來說,樓主想要的是不能實現的. IO就算了... 內存方面我能想到最最接近樓主要求的就是原子操作了,但願樓主要操作的內存片段別超過16byte.另外lockfree技巧也能有些近似地實現樓主的要求.


這個描述很有迷惑性,我們換個思路來看這個問題就好了。

如何讓一個程序在其隨時都有可能被終止的情況下記錄資料庫,保證要麼完全更改要麼完全不更改?

就會發現這就是個普通的一次性提交而已。簡單來講,就是先花時間把東西放到那裡,最後再以很短的時間做一個生效的指令,這個生效指令所花時間極短以至於你無法在其中讓其終止。在生效指令執行之前,所有放在那裡的東西都是無效的,可以看待成不存在。

基本的資料庫例如MySQL都有類似的操作。


我們有Software Transaction Memory,沒什麼人用就是了


Software transactional memory 對於上面IO的疑問,這裡也提到

On the other hand, the need to abort failed transactions also places
limitations on the behavior of transactions: they cannot perform any
operation that cannot be undone, including most I/O. Such limitations
are typically overcome in practice by creating buffers that queue up the
irreversible operations and perform them at a later time outside of any
transaction. In Haskell, this limitation is enforced at compile time by the type system.


這種機制的用處是? 碰上IO指令, 這個機制就完蛋了...


一般這種需求不就是寫個長度為2的數組來回切active元素的下標嗎,更新一個元素哪怕需要100條指令,更新個下標還是可以用原子操作完成的,只是小心aba問題就可以了。比如在x86上volatile int做自增計數器,按位與個0x1做下標,非x86就用std::atomic&就行。


這種實時要求怎麼看,怎麼像最好在單片機片子里做,然後和主機進行通訊;關中斷,妥妥保證原子操作,知識簡單,實施簡單,接個串口。比起純軟體方案可靠性要強很多。


編譯器做不到這一點。

如果只是寫內存的話,還好辦,把內存數據恢復掉即可(前提是內存事務本身不能出問題),問題是 IO 怎麼辦?你從 USB 寫出去的數據,還能收回來?

還有跨進程通信,你給其他進程發了個消息,然後再發個回滾消息?其他進程懵圈了好不。


根據你的表述, 存在自相矛盾的地方.

"設區間A=[0,x]為程序執行的時間段,a為程序終止運行的時刻",

在"當然a∈A,這種情況下,[0,a]這段時間裡的程序是否被執行過?"

---&>既然從0已經開始執行了, 那麼肯定是執行過的.

---------------------------------

不存在這種機制(如果有, 請告訴我).

程序運行的結果,無非是對資源的修改(一些操作也算在內, 比如向客戶端同性等)

有兩種方法避免.

1. 檢測異常, 就採用類似資料庫回滾的方式. 還原程序所做的操作.

2. 只有在程序運行快完成時, 通過檢測一些變數值來判斷程序運行正常, 這個時候再來修改資源.

-----------------------------------------------

當然, 上面兩種方法也有時間上的局限性,還有一些和用戶操作的局限性.

所以沒有100%有用的辦法, 這就需要的是測試.


推薦閱讀:

如何評價《AWS S3 雲存儲莫名消失:各大網站和 Docker 紛紛中招!》?
初學 C/C++ 時有哪些需要掌握的好習慣?
不寫業務代碼的程序員工作內容是什麼樣子的?
說說你因為數據(代碼)潔癖,干過什麼奇怪的事情?
對於編程思想和能力有重大提升的書有哪些?

TAG:編程語言 | 編程 | C編程語言 | CC | 編譯器 |