【问题标题】:Message passing vs locking消息传递与锁定
【发布时间】:2011-08-21 19:27:38
【问题描述】:

在性能方面,消息传递并发方案和基于锁的并发方案究竟有什么区别?等待锁的线程阻塞,因此其他线程可以运行。结果,我看不出消息传递如何比基于锁的并发更快。

编辑:具体来说,我正在讨论一种像 Erlang 中的消息传递方法,与使用锁(或原子操作)的共享数据方法相比。

【问题讨论】:

  • 您是否可以简单地扩展您的问题?你到底在问什么?案例的一些例子?因为你的问题的“真实”答案 - 就像写一本书:) - 真的很长
  • 这是一个公平的比较吗?这不是苹果和橘子吗?
  • 这个问题是关于比较传统线程和SEDA-like 方法的吗?如果是的话,那么我的理解是线程阻塞涉及显着的性能开销(内存围栏等)。你可以看看讨论:How to significantly improve java performance?
  • +1,这是一个非常重要的问题。虽然好像还没有被问过。

标签: concurrency message-passing


【解决方案1】:

正如其他人所建议的(“苹果和橙子”),我认为这两种技术是正交的。这里的基本假设似乎是一个人将选择一个或另一个:我们将使用锁定和共享资源或我们将使用消息传递,并且一个使另一个变得不必要,或者也许另一个甚至不可用。

就像一个元循环求值器,这里不明显哪些是真正的原语。例如,为了实现消息传递,您可能需要原子的 CAS 和特定的内存可见性语义,或者可能需要一些锁定和共享状态。一种可以用锁来实现原子操作,也可以用原子操作来实现锁(就像Java 在其java.util.concurrent.locks 类型中所做的那样)。

同样,虽然可以接受,但可以通过消息传递来实现锁定。一般而言,询问哪个性能更好并没有多大意义,因为这实际上更多的是关于哪个是根据哪个构建的问题。最有可能的是,一个有能力的程序员可以比建立在顶层的程序员更好地驾驶较低级别的汽车——直到最近手动变速器汽车的情况一直如此(那里也有很大的争论) .

通常,人们称赞消息传递方法不是为了更好的性能,而是为了安全和方便,并且通常通过拒绝程序员控制锁定和共享资源来推销它。结果,它赌的是程序员的能力。如果程序员无法获得锁,他就不能做得很差并减慢程序的速度。就像关于手动内存管理和垃圾收集的辩论一样,有些人会声称自己是“好司机”,充分利用手动控制;其他人(尤其是那些实施和推广使用垃圾收集器的人)会声称,总的来说,收集器可以比“不太好的驱动程序”通过手动管理做得更好。

没有绝对的答案。这里的区别在于程序员的技能水平,而不是他们可能使用的工具。

【讨论】:

    【解决方案2】:

    恕我直言,消息传递可能不完全是一种并发方案。它基本上是(IPC)进程间通信的一种形式,是共享对象的替代方案。 Erlang 只支持将消息传递给共享对象。

    共享对象的缺点(优点消息传递):

    • 在多个线程同时运行的上下文中,可变/共享对象的状态更难推理。
    • 在共享对象上同步会导致算法本质上不是wait free 或非lock free。
    • 在多处理器系统中,共享对象可以跨处理器缓存复制。即使使用不需要同步的基于比较和交换的算法,也有可能会花费大量处理器周期向每个处理器发送缓存一致性消息。
    • 由消息传递语义构建的系统本质上更具可扩展性。由于消息传递意味着消息是异步发送的,因此在接收者对消息采取行动之前,发送者不需要阻塞。

    共享对象的优点(消息传递的缺点):

    • 有些算法往往要简单得多。
    • 需要锁定资源的消息传递系统最终会退化为共享对象系统。当程序员开始使用 ets 表等来存储共享状态时,这在 Erlang 中有时很明显。
    • 如果算法无需等待,您将看到性能提高并减少内存占用,因为新消息形式的对象分配要少得多。

    【讨论】:

      【解决方案3】:

      当您只想锁定错误时使用消息传递。在这些情况下,请使用锁定。然而,消息传递给你的不仅仅是锁定——顾名思义,它允许你在线程或进程之间传递消息,即数据。

      【讨论】:

        【解决方案4】:

        消息传递(带有不可变消息)更容易正确处理。使用锁定和共享可变状态很难避免并发错误。

        至于性能,最好自己衡量。每个系统都是不同的——工作负载特征是什么,操作是否依赖于其他操作的结果,或者它们是完全独立还是大部分独立(这将允许大规模并行),延迟或吞吐量更重要,有多少机器等等。可能会更快,或者消息传递可能会更快,或者完全不同。如果与LMAX 相同的方法适合手头的问题,那么也许就是这样。 (我会将 LMAX 架构归类为消息传递,尽管它与基于参与者的消息传递非常不同。)

        【讨论】:

          【解决方案5】:

          消息传递不使用共享内存,也就是说它不需要锁,因为每个线程(进程)只能加载或存储自己的内存,它们之间的通信方式是发送和接收消息。

          【讨论】:

            猜你喜欢
            • 2013-08-24
            • 2022-01-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-09-16
            • 1970-01-01
            相关资源
            最近更新 更多