經由FCC同學提醒,我才發現,之前的兩篇用volatile的無鎖通信,確實是敗在了優化上了。編譯器和CPU硬件會無情的擊毀我們認為的執行順序。
這篇(0)就是否定掉前兩篇,然后在未來的(3)和(4)里面,將用cas等原語來重新設計這個無鎖的通信。
關于編譯器的優化,我猜是為了CPU的U/V流水線來做的。它讓狀態的修改操作,有可能在操作之前就發生了,從而直接顛覆了整個方法。
另外shbooom所說的,兩個原子操作的問題。可能是少打了一個不字。
我說的原子操作,是在最終操作上來理解的,或者稱為內部因果關聯上。就是說,對狀態賦值前的取地址操作,都不算作賦值操作的一部分。同樣的對狀態進行檢查的時候的取地址操作,也不算作檢查的一部分。因為他們互不影響。最終影響檢查狀態的,只有寫內存位置的那一個操作。在這之間出現的執行穿插,最多會導致本次檢查無法命中,但下次檢查就一定會命中。
[Barrier]
在多篇文章中,我找到了解決辦法。可以通過Barrier結束掉之前的所有讀寫操作,從而讓設置狀態這個操作的寫操作不會被優化到實際任務操作的中間或者前面去。
在VC中,有_ReadBarrier _WriteBarrier 和 _ReadWriteBarrier的特殊指令,可以將之前的所有對內存的讀和寫或者讀寫的優化限制到Barrier之前,從而不會把后面的操作優化到前面去。
在其他的編譯器中,應該也有相應的東西來保障執行順序。
不過我還沒測試過這個對性能帶來的影響。希望不要太大。