当前位置: 首页 > 面试题库 >

同步块-锁定多个对象

司空赞
2023-03-14
问题内容

我正在建模一个游戏,其中多个玩家(线程)同时移动。玩家当前所在位置的信息被存储两次:该玩家具有一个变量“
hostField”,该变量引用板上的一个字段,每个字段都有一个ArrayList,用于存储当前位于该字段的玩家。

我对拥有冗余信息的事实不是很满意,但是我发现如果不遍历大数据集就无法避免这种情况。

但是,当玩家从一个字段移到另一个字段时,我想确保(1)冗余信息保持链接(2)此刻没有其他人在操纵该字段。

因此,我需要做类似的事情

synchronized(player, field) {
    // code
}

这是不可能的,对吧?

我该怎么办?:)


问题答案:

实际上,同步是针对代码的,而不是对象或数据的。在同步块中用作参数的对象引用表示锁定。

因此,如果您有如下代码:

class Player {

  // Same instance shared for all players... Don't show how we get it now.
  // Use one dimensional board to simplify, doesn't matter here.
  private List<Player>[] fields = Board.getBoard();

  // Current position
  private int x;

  public synchronized int getX() {
    return x;
  }

  public void setX(int x) {
    synchronized(this) { // Same as synchronized method
      fields[x].remove(this);
      this.x = x;
      field[y].add(this);
    }
  }
}

然后,尽管处于同步块中,但由于锁不相同(它在不同的实例上),所以对字段的访问不受保护。因此,您的董事会的球员名单可能会变得不一致,并导致运行时异常。

相反,如果您编写下面的代码,它将起作用,因为我们只有一个共享锁可供所有玩家使用:

class Player {

  // Same instance shared for all players... Don't show how we get it now.
  // Use one dimensional board to simplify, doesn't matter here.
  private List<Player>[] fields;

  // Current position
  private int x;

  private static Object sharedLock = new Object(); // Any object's instance can be used as a lock.

  public int getX() {
    synchronized(sharedLock) {
      return x;
    }
  }

  public void setX(int x) {
    synchronized(sharedLock) {
      // Because of using a single shared lock,
      // several players can't access fields at the same time
      // and so can't create inconsistencies on fields.
      fields[x].remove(this); 
      this.x = x;
      field[y].add(this);
    }
  }
}

请确保仅使用一个锁来访问所有播放器,否则板的状态将不一致。



 类似资料:
  • 在示例代码中 在这个页面上, lock1和lock2分别控制c1和c2上的更新。 然而, 正在获取对象lock1的锁并在同步块时释放它 被执行。 当这个代码块被执行时,这个对象的成员c1上可能还有一个更新——我看不出这个更新是如何被代码中的lock1上的同步所阻止的。 只有对象lock1可以独占访问——除此之外别无它物(?) 那么,实施情况如何 在上面的代码中不同于 甚至 当c1是一个对象而不是一

  • 问题内容: 输出是 线程1开始 线程1的内部演示 线程2开始 线程2的内部演示 由于,执行尚未结束。 我已经通过类的同一个实例来的两个类的构造函数和。 对in 的调用位于一个块中。 要在通话中是 没有 的块。 所以,当被执行时,由于块,的监视器应锁定,导致拒绝访问,以由所述。 但是,这没有发生。 预期的输出是 (输出在完成之前。) 因此,我的基本问题是: 即使 尚未完成 块, 如何成功执行? 问题

  • 假设我有两条线。Thread1正在访问一个同步方法,同时,Thread2正在访问同一对象的另一个同步方法。据我所知,Thread2应该等到Thread1完成它的任务。我的问题是,Thread2是否在对象的等待线程列表中?对我来说似乎是这样,但Thread2不调用wait()方法,那么作为逻辑结果,它不应该在对象的等待线程列表中。如果它不在对象的等待线程列表中,那么Thread2的状态是什么?

  • 我在学习K K 当一个方法从同步块中执行代码时,代码被称为在同步上下文中执行。当您同步一个方法时,用于调用该方法的对象是必须获取其锁的对象。但是当我们同步代码块时,您必须指定要使用哪个对象的锁作为锁。 在本例中,会在AccountDanger实例或Account对象上获取锁吗?我想应该是这样的。我感觉正确吗?如果它是AccountDanger对象,并且一个线程已获得AccountDanger锁,那

  • 尝试可视化和理解同步。 对同步块使用静态锁定对象(代码a)和非静态锁定对象(代码B)之间有什么区别 它在实际应用中有什么不同 一方会有哪些陷阱而另一方不会 确定使用哪一个的标准是什么 代码A 代码B 笔记 上面的代码显示了构造函数,但是您可以讨论静态方法和非静态方法中的行为是如何不同的。另外,在同步块修改静态成员变量时使用静态锁是否有利? 我已经看过了这个问题的答案,但是还不清楚不同的使用场景是什

  • 如果我没有错的话,Thread-1和thread-3正在进入synchronized方法,因为它有两个不同的目标对象。但是为什么线程2进入同步块呢? 请帮助我理解这一点。提前谢了。