摩托罗拉|即使在计算机的世界,同时性也只是相对的

摩托罗拉|即使在计算机的世界,同时性也只是相对的

爱因斯坦告诉我们:同时性是相对的 。 也即:在不同的地点发生的两个事件 , 在一个惯性系里是同时的 , 但在另一个惯性系里看来却不是同时的 。 而在计算机的世界里 , 同时性也是相对的 。 容我慢慢道来 。
有些开发者会问:”是否可以同时在一个线程里执行操作A而在另一个线程中执行操作B?” , 下面是一些具体的例子:
> X操作:关闭某个句柄 , Y操作:使用这个句柄 。
> X操作:在一个句柄上执行
UnregisterWaitForSingleObject , Y操作:在相同的句柄上执行UnregisterWaitForSingleObject 。
我想 , 你应该可以在不知晓任何内部原理的情况下回答这些问题 。 你只需要知道一些物理知识以及关于什么是”有效顺序代码(valid sequential code)” 。
让我们实际做一个思维实验加深对这个同时性的理解 。
如文章开头所说的 , 同时性是相对的 , 所以任何同时执行X和Y的代码 , 都可以通过实验观察到 , 在Y之前执行X , 或在X之前执行Y , 这取决于你使用的参考框架 。
因此 , 如果可以同时执行它们 , 那么也必然可以一个接一个地先后执行它们 , 因为如果你从底层的原理上考察一个计算机体系 , 可以知道:它们确实会一个接一个地先后执行的 。
在关闭一个句柄后是否可以继续使用这个句柄? 是否可以在一个事件上解除等待两次?
以上两个问题的答案是:不可以 。 也即 , 我们不能同时性地执行这些操作 。
如果你不喜欢使用物理学来解答这些疑问 , 你可以通过下面的技术性思考进行理解 。
调用一个函数并非一项原子性操作 。 实际上它包含几个步骤:准备参数 , 调用函数入口点 , 函数执行操作 , 返回值 。 即使你有办法在两个线程中同时到达函数入口点(实际上从物理层面上我们无法真正同时地执行两个操作) , 也会存在这样一种可能性:在”call”指令将控制权转移到目标函数的第一条指令后 , 一个线程总是有可能立即被抢占 , 而另一个线程继续完成 。 在第二个线程运行完成后 , 被抢占的线程被调度并开始执行函数体 。
在这种情况下 , 你实际上是一个接一个地先后调用了这两个函数 , 尽管你努力同时调用它们 。由于这种情况总是有可能发生的 , 在编写并发代码时 , 需要考虑这种可能性 。
希望这第二种技术性解释能让那些不相信物理力量的人满意 。
就个人而言 , 我更喜欢使用物理学原理 。
总结多线程里的并发性设计 , 需要在心中时时刻刻问自己:是否有其他线程里的代码尝试修改这个变量?
最后Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一 , 里面有很多关于Windows的小知识 , 对于广大Windows平台开发者来说 , 确实十分有帮助 。
本文来自:《Even in computing simultaneity is relative》
【摩托罗拉|即使在计算机的世界,同时性也只是相对的】