9

所以假设我有一个N大小的服务器阵列,如下所示:

替代文字 http://www.terracotta.org/web/download/attachments/43909161/ServerArrayMirrorGroup.png

我有一个简单的 JavaBean/POJO:

package example;

public class Person {
  private OtherObject obj;

  public void setObj(OtherObject theObj) {
    synchronized (this) {
      obj = theObj;
    }
  }

  public OtherObject getObj() {
    synchronized (this) {
      return obj;
    }
  }
}

现在,如果其中一个客户端在 TC 根(数据结构)中的 Person 对象上调用 Person.setObj(OtherObject),则该客户端上的同步块(在 Person.setObj(OtherObject) 中)持有:

1) 直到N大小的服务器阵列中的所有N个服务器都已与该 Person.obj 属性同步/更新?

或者

2) 直到“活动”服务器与更新的 Person.obj 属性同步?那么阵列中的其他(N-1)台服务器是否尽可能同步?

或者

3)我正在寻找其他一些方法?

4

3 回答 3

5

答案不是真正的 1 或 2。对象是跨服务器镜像组条带化的。第一次设置此字段时,会创建一个事务,为第一个事务选择的镜像组将在此之后“拥有”该对象。

对于 1 和 2,并非所有活动服务器组都需要更新,因此无需等待其中任何一个条件。

您可以在 Terracotta 文档中找到有关配置 Terracotta 服务器阵列的更多信息:

从锁定的角度来看,在执行对象修改时,将持有此 Person 对象上的集群锁(跨集群互斥)。同步块的范围形成了上面提到的事务。在 getObj() 方法中,您可以将其配置为读取锁,这将允许跨集群的多个并发读取器。

于 2009-05-04T14:24:55.907 回答
3

假设其他人都引用了您的对象,并且可以在您这样做时/之前/之后触摸它。因此解决方案是添加锁,并且

  • 获得锁
  • 修改对象
  • 释放锁

这正是synchronized所做的......它创建了一个队列,并且同步方法不能被多次调用......但是如果在某处引用了底层对象,它可能会被触及。

看:

于 2009-05-03T22:52:19.220 回答
0

我不熟悉他们的(Terracotta)实现,但从 JMM 的角度来看,它应该采用集群范围的锁。然而,这个例子非常简单;只是一个引用的改变,这可能会导致它被转换成更像是一个 volatile write 的东西,并且完全避免了锁定。

但是,如果您在同步块中做一些重要的事情,那么我会假设 TC 在同步块开始时悲观地采用集群范围的锁。如果他们不这样做,他们将与 JMM 规范不一致。据我了解。

换句话说,您的选项#1。因此,请注意您在集群中共享的内容,并尽可能使用不可变对象和 java.util.concurrent.* 数据结构 - 后者在 TC 中得到了特别的内在喜爱。

于 2009-05-03T00:31:27.087 回答