考虑这两个代码示例:
private final Player[] players = new Player[MAX_PLAYERS + 1];
private int playerCount;
public boolean addPlayer(Player player) {
synchronized (players) {
for (int i = 1; i < players.length; i++) {
if (players[i] == null) {
players[i] = player;
playerCount++;
player.setIndex(i);
return true;
}
}
return false;
}
}
public void removePlayer(Player player) {
synchronized (players) {
players[player.getIndex()] = null;
playerCount--;
}
}
public Player[] getPlayers() {
synchronized (players) {
return players;
}
}
public int getPlayerCount() {
synchronized (players) {
return playerCount;
}
}
和...
private final AtomicReferenceArray<Player> players = new AtomicReferenceArray<Player>(MAX_PLAYERS + 1);
private final AtomicInteger playerCount = new AtomicInteger();
public boolean addPlayer(Player player) {
for (int i = 1; i < players.length(); i++) {
if (players.get(i) == null) {
players.set(i, player);
playerCount.incrementAndGet();
player.setIndex(i);
return true;
}
}
return false;
}
public void removePlayer(Player player) {
players.set(player.getIndex(), null);
playerCount.decrementAndGet();
}
public AtomicReferenceArray<Player> getPlayers() {
return players;
}
public AtomicInteger getPlayerCount() {
return playerCount;
}
现在,我知道通常访问数组是非常有效的。但是,我知道同步可能代价高昂。另一方面,原子操作不需要同步,但我猜这players.get(i)
不如players[i]
. 那么,如果我在游戏环境中使用这些样本中的哪一个会给我最好的性能呢?我设计了服务器,以便每个新玩家都有一个专用于他们的线程。每次他们完成连接和登录后,他们都会通过 将自己添加到玩家列表中addPlayer(Player)
。当玩家断开连接时,他们会通过 将自己从玩家列表中删除removePlayer(Player)
。由于这些操作是从不同的线程调用的,因此肯定需要同步。那么我应该使用哪个?