私は2つのロックinventoryLockとcurrencyLockを持つオブジェクトUserを持っています。多くの場合、これらのロックは個別に使用されます。簡単に作成されたデッドロックを回避するにはどうすればよいですか?
synchronized (user.inventoryLock) {
// swap items
tmp = user.inventory[x];
user.inventory[x] = user.inventory[y];
user.inventory[y] = tmp;
}
又は
synchronized (user.currencyLock) {
if (user.money < loss) throw new Exception();
user.money -= loss;
}
しかし、時にはコードの一部は、両方のロックを必要とする:
synchronized (user.currencyLock) {
synchronized (user.inventoryLock) {
if (user.money < item.price) throw new Exception();
user.money -= item.price;
user.inventory[empty] = item;
}
}
はシンプルだが、ちょうどこの例よりも、両方のロックを使用してコードのより多くのビットがあり、以前の経験から、複数のコードに同じ共有ロックが必要な場合、デッドロックの危険性があることがわかっています。
これを避けるにはどうすればよいでしょうか?
2つのオブジェクトを原子的にロックするメカニズムがありますか?
あなたのコードは、カプセル化の深刻な欠如を示しています。メソッドを実行することなく、ユーザーの状態に直接アクセスします。状態をクラスにカプセル化して同期を集中化し、必要な同期がすべて完了したことを確認する必要があります。 Userクラス自体にこのサービスを提供するのではなく、ユーザーのすべてのクライアントを適切に同期させる必要があります。 –
@JBNizetこれは単なるコード例です。実際のコードには、とりわけ、ユーザークラスが実行できないデータベース呼び出しが含まれます。 –