synchronized块 - 锁定多个对象 [英] synchronized block - lock more than one object

查看:221
本文介绍了synchronized块 - 锁定多个对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为多个玩家(线程)同时移动的游戏建模。
此时玩家所处位置的信息被存储两次:玩家有一个变量hostField,它引用棋盘上的一个字段,每个字段都有一个ArrayList,用于存储当前位于此处的玩家字段。

I'm modelling a game where multiple players (threads) move at the same time. The information of where a player is located at the moment is stored twice: the player has a variable "hostField" that references to a field on the board and every field has an ArrayList storing the players that are currently located at this field.

我对我有冗余信息这一事实并不十分满意,但我发现如果不循环使用大数据集,我就无法避免这种情况。

I'm not very happy with the fact that I have redundant information, but I found no way avoiding that without looping through a big dataset.

然而,当玩家从一个领域移动到另一个领域时,我想确保(1)冗余信息保持联系(2)此刻没有其他人操纵该领域。

However, when a player moves from one field to another, I'd like to make sure (1) the redundant information stays linked (2) nobody else is manipulating the field at the moment.

因此我需要做类似的事情

Therefore I need to do something like

synchronized(player, field) {
    // code
}

这是不可能的,对吗?

我该怎么办? :)

推荐答案

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

In fact, synchronization is for code, not objects or data. The object reference used as a parameter in synchronized block represent the lock.

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

So if you have code like:

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);
    }
  }
}

然后尽管在同步阻止对字段的访问不受保护,因为锁不相同(它在不同的实例上)。因此,您的电路板的播放器列表可能会变得不一致并导致运行时异常。

Then Despite being in the synchronized block the access to field is not protected because the lock is not the same (it being on different instances). So your List of Players for your board can become inconsistent and cause runtime exceptions.

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

Instead if you write the following code, it will work because we have only one shared lock for all players:

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);
    }
  }
}

请务必仅使用单锁可以访问所有玩家或你的董事会状态不一致。

Be sure to use only a single lock to access all the players or your board's state will be inconsistent.

这篇关于synchronized块 - 锁定多个对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆