2011-07-15 3 views
3

一般的な変数にアクセスするためにスレッドを同期させたい。 私はN個のスレッドを持ち、それぞれがTSyncThreds型の変数のグローバルインスタンスにアクセスできるとします。TCriticalSectionは変数へのマルチスレッドアクセスを許可しますか?

IncCount、DecCountメソッドを呼び出すことはできますか?または、オブジェクトの同じインスタンスにアクセスする同時スレッドに問題がありますか?

私はちょうどFCcounter変数へのアクセスをシンクロ...

type 
    TSyncThreads = class 

    public 
    FCounterGuard: TCriticalSection; 
    FCounter: integer; 
    FSimpleEvent: TSimpleEvent; 

    constructor Create(); 
    procedure Wait(); 
    procedure IncCounter(); 
    procedure DecCounter(); 
    end; 


var 
    SyncThread: TSyncThreads; 

implementation 
uses 
    Math, Windows, Dialogs; 



{ TSyncThreads } 

procedure TSyncThreads.DecCounter; 
begin 
    FCounterGuard.Acquire; 
    Dec(FCounter); 
    if FCounter = 0 then 
    FSimpleEvent.SetEvent; 
    FCounterGuard.Release; 
end; 

procedure TSyncThreads.IncCounter; 
begin 
    FCounterGuard.Acquire; 
    Inc(FCounter); 
    FCounterGuard.Release; 
end; 

constructor TSyncThreads.Create(); 
begin 
    FCounter := 0; 
    FSimpleEvent := TSimpleEvent.Create; 
    FCounterGuard := TCriticalSection.Create; 
    FSimpleEvent.ResetEvent; 
end; 

procedure TSyncThreads.Wait; 
var 
    ret: TWaitResult; 
begin 
    ret := FSimpleEvent.WaitFor(INFINITE); 
end; 
+0

クリティカルセクションを保持している間に何か問題が発生した場合にReleaseが呼び出されるように、try/finallyブロックでAcquure/Releaseの呼び出しをラップする必要があります。さもなければ、それは決して解放されることができず、獲得するのを待っているものであればブロックされません。 –

答えて

8

当面の作業のためのビット過剰場合は、[はい、あなたのコードは、罰金です。同じオブジェクトにアクセスする複数のスレッドについて心配していますが、それはまさにTCriticalSectionやTEventのような同期オブジェクトのために設計されたものです。同時にアクセスすることができない場合、そのようなクラスがどれほど無意味であるかを想像してみてください。

カウンターへのアクセスを保護するために重要なセクションは本当に必要ありません。 InterlockedIncrementとInterlockedDecrementを使用すると、より軽量なアクセスが可能です。彼らは変数の前の値を返します。したがって、InterlockedDecrementが1を返した場合、あなたのイベントを設定する時間だと分かります。

カウンタに上限がある場合は、このコードをすべて避けてセマフォを使用することさえできます。または、各スレッドに独自のイベントを設定し、WaitForMultipleObjectsを使用してすべてのイベントを待機させることもできます。すべてのスレッドがイベントを設定したら戻ってくるので、共有変数へのアクセスを同期させる必要はありません。

+0

ありがとう! 私は連動した汚れが好きです。 –

+0

Interlocked *関数を使用する場合、カウンタのアドレスは4で割り切れる必要があります。また、インターロックされた関数などを提供するmy TGp4AlignedIntレコードを使用してください。http://gpdelphiunits.googlecode.com/svn/trunk/ src/GpStuff.pas。 – gabr

+0

整数変数が正しく整列されない唯一の時間は、パックされたレコードのメンバである場合です。グローバル、ローカル、パラメータ、およびクラスフィールドは常に整列します。 –

関連する問題