zl程序教程

您现在的位置是:首页 >  硬件

当前栏目

即使在计算机的世界,同时性也只是相对的

计算机 世界 只是 相对 即使
2023-09-14 09:10:44 时间

爱因斯坦告诉我们:同时性是相对的。也即:在不同的地点发生的两个事件,在一个惯性系里是同时的,但在另一个惯性系里看来却不是同时的。而在计算机的世界里,同时性也是相对的。容我慢慢道来。

有些开发者会问:”是否可以同时在一个线程里执行操作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》

最近我写了个东西

正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。