これは、デッドロックを伴う模擬銀行データベースの問題です。私はすでに答えだと思うものを持っていますが、これが良い解決策であるかどうか興味があります。提起された質問は次のとおりです。
次のコードでデッドロックを防ぐにはどうすればよいですか?:
void transaction(Account from, Account to, double amount)
{
Semaphore lock1, lock2;
lock1 = getLock(from);
lock2 = getLock(to);
wait(lock1);
wait(lock2);
withdraw(from, amount);
deposit(to, amount);
signal(lock2);
signal(lock1);
}
これがデッドロックになる可能性がある方法は、2つのスレッド(またはプロセス?)を介して、反対のアカウントで同時にtransaction()メソッドを呼び出すことです。
トランザクション(貯蓄、チェック、1); スレッド1と
トランザクション(チェック、貯蓄、2); スレッド2で。
私の理解が不十分なため、何が起こっているのか、なぜデッドロックになっているのかは、両方のスレッドが(互いに?)ロックを取得しようとしているため、ロックの順序に従わないためだと思います。
私の手っ取り早い解決策は、関数transaction()の外で、呼び出されたときに次のようになる場所にロックを移動することです。
//somewhere in main
Semaphore lock1, lock2;
lock1 = getLock(from);
lock2 = getLock(to);
wait(lock1);
wait(lock2);
transaction(checking, savings, 2);
signal(lock2);
signal(lock1);
//.....
トランザクションは次のようになります。
void transaction(Account from, Account to, double amount)
{
withdraw(from, amount);
deposit(to, amount);
}
そうすれば、トランザクションは技術的に重要なセクションであるため、同時に実行することはできません。これがJavaプログラムの場合、関数宣言のvoidの後にsyncedという単語を入れてモニターを使用することもできますか?それはうまくいくでしょうか?それはそれを行うためのより賢い方法のようです。
私もこれをまったく理解していないかもしれないので、特に私の説明が正確でない場合は、遠慮なく私を学校に通してください。ありがとう。