2

私はdelphi XE2で比較的新しいです。このコードが好きなら、何かについて知りたいです

TSomeClass=class
strict private
class var
   FCounter:integer;
public
   class procedure SomeProcedure();static
end;

implementation
class procedure SomeProcedure()
begin
  inc(FCounter);
end;

initialization
begin
   FCounter:=0;
end;

finalization
begin
  FCounter:=0;
end;

私の理解では、 SomeProcedure() はメモリ上で静的になり、単一のインスタンス、

私の質問

  1. TSomeClass が多くのスレッドによってアクセスされる場合、TSomeClass はスレッドセーフかどうか? または、スレッド間でオーバーラップしますか?
  2. はいの場合、スレッドごとにクリティカル セクションが必要ですか? またはその種の方法の別のアプローチ...
  3. 2 つの異なるスレッドがこのメソッドにアクセスした場合、FCounter はどうですか? FCounter は、最後の値から順番にカウントしますか、それともゼロから始まる別の値を持つ別のスレッドですか?
4

2 に答える 2

7

メソッドの異なる呼び出し間の同期はありません。メソッドの種類に関係なく、メソッドが共有データにアクセスする場合は、同期が必要になる場合があります。

それらのメソッドがクラス メソッドであろうとインスタンス メソッドであろうと、静的メソッドであろうと動的メソッドであろうと、違いはありません。重要なのは、複数のスレッドからアクセスされる共有オブジェクトがあるかどうかだけです。

2 つの異なるスレッドがこのメソッドにアクセスした場合、FCounter はどうでしょうか? FCounter は、最後の値から順番にカウントしますか、それともゼロから始まる別の値を持つ別のスレッドですか?

あなたのコードでFCounterは、クラス変数です。変数の単一のインスタンスがあり、すべてのスレッド間で共有されます。クラス変数は単なるグローバル変数であり、それ以上でもそれ以下でもありません。

コードはその共有変数を変更します。書かれているように、コードにはデータ競合があります。同期で解決できます。たとえば、InterlockedIncrementではなくを使用しincます。

class procedure SomeProcedure;
begin  
  InterlockedIncrement(FCounter); 
end;

より複雑なオブジェクトの場合は、クリティカル セクションでシリアル化します。

于 2013-05-23T06:03:59.720 に答える
5

あなたのクラスはスレッドセーフではありません。

カウンター スレッド セーフを取得する最も簡単な方法は、Inc(FCounter) の代わりに TInterlocked.Increment(FCounter) を使用することです。すべての TInterlocked メソッドはアトミック操作として実行されます。同じことが、ここでも使用できる Windows API 関数 InterlockedIncrement() にも当てはまります。

于 2013-05-23T07:07:03.913 に答える