Mロックを使用する時は、より良く設計されていて定義されているロックプロトコルを使用する必要があります。ロックプロトコルでは、、ロックを取得し、タイムアウトを選択して使用し、Mロックを解放し、与えられた状況に従ってロック計画を定義し、潜在的なデッドロックの状況を識別し、デッドロックを避けるべきかまたは回復すできかの手段を提供などのために、ガイドラインを設定する必要があります。このセクションでは、2つの演習が含まれています。1番目の演習では、以前にこの章で説明したGT.Mロックの概念を補強します。2番目の演習は、デッドロックの状況を解説し、デッドロックを識別して解決するためにLKEが使用できる1つの方法を示します。
二人のユーザ(ジョンさんとトムさん)が、排他的にグローバル変数^ABC
を更新する必要がある時の状況を考えてみます。
注意 | |
---|---|
トランザクション処理は、潜在的な更新の競合(コンフリクト)の問題に対して、より効率的で、そして、より簡単に管理できるソリューションを提供します。詳細については、GT.Mプログラマーズガイド の Mの一般的な言語機能 の章を参照してください。 |
ジョンさんがGT.Mプロンプトで、次のコマンドを実行します。
GTM>lock +^ABC
このコマンドは、"^ABC
"上にGT.Mロックをかけます(グローバル変数^ABC
では無い)。注:+/- の無いロックは、常にプロセスによって保持されているすべてのロックを解放します。これらは暗黙的にデッドロックを回避します。 LOCK +
のプロトコルは(デッドロックを避けるために)同じ順序でロックを蓄積する必要があります。
その後、ロックデータベースの状態を表示するには、次のコマンドを実行します。
GTM>zsystem "lke show -all"
このコマンドは、以下の出力を生成します:
DEFAULT ^ABC Owned by PID= 3657 which is an existing process
今、^ABC
のロックを解放せずに、トムさんのGT.Mプロンプトで次のコマンドを実行します。
GTM>lock +^ABC
このコマンドは、解放されるまで "^ABC
" のリソース上のロックを待ちます。LOCKコマンドは、多少なりともグローバル変数^ABC
をブロックしないことに注意して下さい。このコマンドは、LOCKデータベースに"^ABC"
のリソースをロックするための要求を待ち行列(キュー)に格納します。たとえグローバル変数^ABC
がジョンさんによってロックされていたとしても、その値をそれでも変更できることに注意してください。
今、ジョンさんのGT.Mプロンプトで、次のコマンドを実行します。
GTM>zsystem "LKE -show -all -wait"
このコマンドは、以下の出力を生成します:
DEFAULT ^ABC Owned by PID= 3657 which is an existing process Request PID= 3685 which is an existing process
この出力では、PID 3657でジョンさんに属するプロセスが、現在、グローバル変数^ABC
のロックを所有していることと、そして、トムさんのPIDがそのロックの所有権を要求していること、を示しています。あなたが同時アクセスのプロトコルに従ってアプリケーションロジックを作成するには、このメカニズムを使用することができます。
これらユーザ(ジョンさんとトムさん)の両方が2つのテキストファイルを更新する必要がある時には、今、別の状況を考えてみましょう。更新が進行中に、GT.MのLOCKは、他のユーザがそのファイルをロックすることを防ぐ必要があります。いくつかのケースでは、新たな追加のロックを追加する前に、それらがそれら現在のロックを解放しないので、両方のユーザとも次に進むことができない、デッドロックが発生します。
デッドロックの状況は、次のような状況で発生する可能性があります。
John Tom LOCK +file_1 LOCK +file_2 LOCK +file_2 LOCK +file_1
ここでは、両方のユーザがデッドロックされており、どちらも次に進むことができません。デッドロックの状況が実際には基になるリソースをブロックしないことに注意してください。
今このような状況を作ってみましょう。
ジョンさんがGT.Mプロンプトで、次のコマンドを実行します。
GTM>set file1="file_1.txt" GTM>lock +file1 GTM>open file1:APPEND GTM>use file1 GTM>write "John",! GTM>close file1
ジョンさんは、リソース "file1" のロックをリリースしていないことに注意してください。
トムさんのGT.Mプロンプトで、次のコマンドを実行します。
GTM> set file2="file_2.txt" GTM> lock +file2 GTM> open file2:APPEND GTM> use file2 GTM>write "Tom",! GTM>close file2
トムさんは、リソース"file2" のロックをリリースしていないことに注意してください。
今、ジョンさんのGT.Mプロンプトで、次のコマンドを実行します。
GTM>set file2="file_2.txt" GTM>lock +file2
後者のコマンドは、既にトムさんによってロックされている file2
のリソース上でロックしようと試みます。したがって、この結果は、デッドロックの状況です。トムさんのために同じプロセスを繰り返し、リソースfile1
をロックしようとします。
このデッドロック状態を表示するには、LKEプロンプトで次のコマンドを実行します。
LKE>show -all -wait file1 Owned by PID= 2080 which is an existing process Request PID= 2089 which is an existing process file2 Owned by PID= 2089 which is an existing process Request PID=2080 which is an existing process
ロックを解放するために他のユーザは待っているので、どちらのユーザも次に進むことができないというデッドロックの状況を示しています。あなたは、 LKE CLEAR -PID
コマンドを使用して、ロックをクリアすることによって、この状況を解決することができます。
注意 | |
---|---|
アプリケーションが予期しない動作につながる可能性があるので、本番(プロダクション)環境でデッドロックをクリアするために |