考虑到作为独立计算引擎(存储是实例变量,CPU 是类方法)响应从一个传递到另一个的消息的对象的核心模型,Smalltalk 似乎很适合并行处理大量的核心。然而,这也是 Smalltalk 确实仍然非常薄弱的一个领域,它依靠自己的模拟多任务处理功能,而这些功能没有利用现代处理器的硬件功能。
为什么是这样?主要问题是什么?可变性是关键,还是更特定于 Smalltalk?
最佳答案
首先,让我们回想一下,GemStone 证明了 Smalltalk 可以扩展以支持并行计算。当然,问题仍然存在,因为 GemStone 是一个非常复杂的系统(想想,例如,在垃圾收集器中!)而所有其他方言都不会这样。
并行计算需要线程安全的代码;否则竞争条件会一直出现。问题是使 Smalltalk 代码线程安全会增加任何地方的复杂性。考虑例如
OrderedCollection >> addLast: anObject
lastIndex = array size ifTrue: [self makeRoomAtLast].
lastIndex := lastIndex + 1.
^array at: lastIndex put: newObject
这些代码行之间的中断可能会使接收器的内部状态不一致。当然,这也可能发生在非并行执行中,因为 Smalltalk 支持中断。然而,Smalltalk 使用此功能的方式仅限于不经常发生的关键部分,因此以某种方式受到控制。
之所以在 Smalltalk 中添加线程安全代码不是那么自然,是因为在 Smalltalk 中我们有一个图像。这意味着所有进程共享大量对象,例如,包括所有类、编译方法等。系统及其应用程序广泛使用的 Smalltalk 的动态特性使事情变得更加困难。
根据我的个人经验,在 Smalltalk 中实现多核功能的一个好方法是启动不同的操作系统进程( headless 镜像的实例)并使用 Smalltalk 信号量和进程协调它们。在这种方法下,每个 OS 进程都由 Smalltalk 进程在主镜像(带有 UI 的镜像)中表示。主镜像和 headless 进程之间的通信可以依赖套接字(或任何其他功能)。当然,您在调试时要付出代价。事实上,您最终会在日志文件中跟踪大量事件并在“ headless ”进程中打开调试器,直到您了解出了什么问题。但是可以做到,不仅仅是作为演示,而是作为真正的“工业强”产品。
关于multithreading - 使 Smalltalk 并行化的难点是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35940570/