经由FCC同学提醒,我才发现,之前的两篇用volatile的无锁通信,确实是败在了优化上了。编译器和CPU硬件会无情的击毁我们认为的执行顺序。
这篇(0)就是否定掉前两篇,然后在未来的(3)和(4)里面,将用cas等原语来重新设计这个无锁的通信。
关于编译器的优化,我猜是为了CPU的U/V流水线来做的。它让状态的修改操作,有可能在操作之前就发生了,从而直接颠覆了整个方法。
另外shbooom所说的,两个原子操作的问题。可能是少打了一个不字。
我说的原子操作,是在最终操作上来理解的,或者称为内部因果关联上。就是说,对状态赋值前的取地址操作,都不算作赋值操作的一部分。同样的对状态进行检查的时候的取地址操作,也不算作检查的一部分。因为他们互不影响。最终影响检查状态的,只有写内存位置的那一个操作。在这之间出现的执行穿插,最多会导致本次检查无法命中,但下次检查就一定会命中。
[Barrier]
在多篇文章中,我找到了解决办法。可以通过Barrier结束掉之前的所有读写操作,从而让设置状态这个操作的写操作不会被优化到实际任务操作的中间或者前面去。
在VC中,有_ReadBarrier _WriteBarrier 和 _ReadWriteBarrier的特殊指令,可以将之前的所有对内存的读和写或者读写的优化限制到Barrier之前,从而不会把后面的操作优化到前面去。
在其他的编译器中,应该也有相应的东西来保障执行顺序。
不过我还没测试过这个对性能带来的影响。希望不要太大。