次の2つのコードサンプルを検討してください。
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)
ます。これらの操作は異なるスレッドから呼び出されるため、同期が確実に必要です。では、どちらを使用すればよいですか?