有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么akka需要不可变的消息

或者换句话说:可变消息是否有适当的用途

我面临的用例是,我希望处理基本上属于类型的对象

Map<String,List<String>>

参与者的典型处理是读取或写入映射的某些字段。一个简明的例子是(省略null-tests等)

  map.get("somekey").add("new value");

我的直觉是,通过使用各自的集合类型,在Scala中保持此不变将是微不足道的。在Java中,它需要一些额外的类库

但是:阅读Akka文档,我发现sending a message introduces a happens-before relation介于发送方的最后一次访问和接收方参与者的第一次访问之间。因此,如果map不是不可变的,那么发送方应该看到所有数据

假设我可以确保发送方在发送map之后再也不会接触它,那么在对该映射进行线程化数据访问方面是否还有其他问题


共 (4) 个答案

  1. # 1 楼答案

    OP对before规则的解释是正确的:“actor发送规则”意味着在A处理M之前向actor A发送M(这就是“相同”所指的)

    回答主要问题:只要最多只有一个参与者可以在任何给定的时间点“拥有”可变映射,这将起作用,并且取决于具体情况,这可能是解决问题的最有效方法。但是,保证单一所有权需要一些规则,这会通过维护成本抵消运行时优势

    虽然最初的问题忽略了传输Map的实际载体,但我想强调Randall的观点,即参与者之间的消息永远不应该是JDK类型,因为它们缺乏语义意义。在这种情况下,Map应该包含在一个明确命名的自定义消息类型中

  2. # 2 楼答案

    简言之,这是一条避免大量奇怪问题的规则

    潜在的问题是,当一个线程修改内存而另一个线程读取该内存时,JavaVM有一些奇怪的规则。如果你想知道血淋淋的细节,谷歌搜索“记忆障碍”

    这意味着VM上运行的每种语言都会受到影响

    这些规则反过来又使得很难判断何时读取某人发送的消息是安全的,因为写入线程可能还没有刷新它的CPU缓存

    解决方案是强制人们使用不可变模式,从那时起,当Akka内核接收消息并将其传递给另一个线程时,VM将确保缓存实际上被刷新

  3. # 3 楼答案

    如果数据实际上是不可变的,您应该不会有问题。如果数据是不可变的,那么这更容易实施,但是通过规程,您可以在发送地图后将其视为有效的不可变

  4. # 4 楼答案

    Akka docs you reference表示before规则只适用于同一个参与者。因此,如果您将消息从一个发送方参与者发送到另一个接收方参与者,则在规则不适用之前发生

    此外,随着代码库的不断发展,“确保”每次修改映射的唯一参与者是原始发送者将变得越来越困难

    为什么不在原始发送者中创建一个新的不可变映射,或者在将消息发送给其他参与者之前修改消息内容的任何其他地方创建一个新的不可变映射呢?然后,您将100%确定没有其他参与者可以修改他们收到的消息,并且您将很容易避免任何并发问题