スレッドから同じメモリ領域への同時アクセスを防止する
これらの基本的なテクニックを使用すると、自分のスレッドと同じメモリに他のスレッドがアクセスしないようにすることができます:
オブジェクトをロックする
- キャンバスのように Lock メソッドを持つオブジェクトの場合、必要に応じて Lock メソッドを呼び出すと、他のオブジェクトがそのオブジェクトにアクセスしないようにでき、ロックが必要なくなったら、Unlock を呼び出します。
- TThreadList.LockList(Delphi)または TThreadList::LockList()(C++)を呼び出すと、スレッドは、リスト オブジェクト TThreadList を使用できなくなります。ロックが不要になったら、TThreadList.UnlockList を呼び出します。
メモ: TCanvas.Lock および TThreadList.LockList は、安全に呼び出すことができます。
クリティカル セクションを使用する
- TCriticalSection のグローバル インスタンスを作成します。
- Acquire メソッドを呼び出し、グローバル メモリにアクセスする間、他のスレッドをロックで排除します。
- Release メソッドを呼び出すと、他のスレッドが Acquire を呼び出すことで、メモリにアクセスできるようになります。次のコードでは、グローバル クリティカル セクション変数 LockXY があり、グローバル変数 X と Y へのアクセスをブロックします。X や Y を使用するには、スレッドは、次のように、クリティカル セクションへの呼び出しで、囲む必要があります:
Delphi:
LockXY.Acquire;
try
X := X + 1;
Y := sin(X);
finally
LockXY.Release
end;
C++:
LockXY->Acquire();
try
{
x++;
y = sin( x );
}
__finally
{
LockXY->Release();
}
警告: クリティカル セクションは、すべてのスレッドが、グローバル メモリにアクセスするためにそれらを使用する場合にのみ、機能します。そうでなければ、同時アクセスの問題が発生します。
複数読み出し/排他的書き込みシンクロナイザを使用する
- TMultiReadExclusiveWriteSynchronizer のグローバル インスタンスを作成します。これは、保護したいグローバル メモリと関連づけられます。
- スレッドはメモリから読み取る前に、BeginRead を呼び出す必要があります。
- メモリ読み込みが完了したら、スレッドは EndRead を呼び出す必要があります。
- スレッドはメモリに書き込む前に、BeginWrite を呼び出す必要があります。
- メモリへの書き込みが完了したら、スレッドは EndWrite を呼び出す必要があります。
警告: 複数読み出し/排他的書き込みシンクロナイザは、すべてのスレッドが、関連付けられたグローバル メモリにアクセスする際に使用した場合にのみ、機能します。そうでなければ、同時アクセスの問題が発生します。