5

usingロックヘルパーとは、ステートメントを介してロックを実装できる使い捨てオブジェクトを指しています。たとえば、Jon Skeet の MiscUtilSyncLockのクラスの典型的な使用法を考えてみましょう。

public class Example
{
    private readonly SyncLock _padlock;

    public Example()
    {
        _padlock = new SyncLock();
    }

    public void ConcurrentMethod()
    {
        using (_padlock.Lock())
        {
            // Now own the padlock - do concurrent stuff
        }
    }
}

ここで、次の使用法を検討してください。

var example = new Example();
new Thread(example.ConcurrentMethod).Start();

私の質問はこれです -exampleはあるスレッドで作成されConcurrentMethod、別のスレッドで呼び出されるため、ConcurrentMethodのスレッドはコンストラクターでの の割り当てを忘れることはできませんでした(_padockスレッドのキャッシュ/読み書きの並べ替えのため)。自体)?NullReferenceException_padLock

Monitor/によるロックにはメモリバリアの利点があることは知っていlockますが、これらのようなロックヘルパーを使用すると、そのようなバリアが保証される理由がわかりません。その場合、私が理解している限り、コンストラクターを変更する必要があります。

public Example()
{
    _padlock = new SyncLock();
    Thread.MemoryBarrier();
}

出典:マルチスレッド アプリにおけるローロック テクニックの影響の理解

EDIT Hans Passant は、スレッドの作成がメモリバリアを意味することを示唆しています。それではどうですか:

var example = new Example();
ThreadPool.QueueUserWorkItem(s => example.ConcurrentMethod());

現在、スレッドは必ずしも作成されているわけではありません...

4

1 に答える 1

10

いいえ、メモリバリアが作成されることを保証するために特別なことをする必要はありません。これは、別のスレッドで実行されるメソッドを取得するために使用されるほとんどすべてのメカニズムが、呼び出しスレッドでrelease -fence バリアを生成し、ワーカー スレッドでaquire-fenceバリアを生成するためです (実際には、それらはフル フェンス バリアである可能性があります)。そのため、QueueUserWorkItemまたはThread.Start必要なバリアが自動的に挿入されます。あなたのコードは安全です。

また、接線上の関心事としてThread.Sleep、メモリバリアも生成されます。Thread.Sleepスレッド インターリーブをシミュレートするために単純に使用する人もいるので、これは興味深いことです。この戦略がローロック コードのトラブルシューティングに使用された場合、見つけようとしていた問題を十分に隠すことができます。

于 2011-07-04T19:33:19.553 に答える