我添加了另一个答案,因为我还没有添加评论给其他人的帖子。
>事实上,同步是用于代码,而不是对象或数据。在同步块中用作参数的对象引用表示锁定。
所以如果你有如下代码:
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[] 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[] 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);
}
}
}
=>确保只使用一个锁来访问所有玩家,否则您的棋盘状态将不一致。