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