实际上,同步是针对代码的,而不是对象或数据。在同步块中用作参数的对象引用表示锁。
因此,如果您有如下代码:
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);
}
}
}
确保仅使用单个锁来访问所有玩家,否则棋盘的状态将不一致。