ロックオブジェクトが静的である必要があるのはなぜですか?


112

マルチスレッドでのロックには、プライベートな静的な読み取り専用オブジェクトを使用することが非常に一般的です。privateは、カプセル化を強化することでロックオブジェクトへのエントリポイントを減らし、したがって最も重要なものへのアクセスを減らすことを理解しています。

しかし、なぜ静的なのでしょうか?

private static readonly object Locker = new object();

最後にフィールドは私のクラス内でのみ使用され、代わりにこれを使用することもできます:

private readonly object Locker = new object();

コメントは?

更新:

例として、このコードを貼り付けました(単なる例)。私はこれに静的または非静的ロッカーを使用することができ、どちらも正常に動作します。以下の答えを考えると、このようにロッカーを定義する必要がありますか?(申し訳ありませんが、来週インタビューがあります。すべての詳細を知る必要があります:)

private readonly object Locker = new object();

そしてここにコードがあります:

    private int _priceA;
    private int _priceB;
    private EventWaitHandle[] _waithandle;
    private readonly IService _service;

//ctor
public ModuleAViewModel(IService service)
    {
        _service = service;
        _modelA = new ModelA();
        _waithandle = new ManualResetEvent[2];
        _waithandle[0] = new ManualResetEvent(false);
        _waithandle[1] = new ManualResetEvent(false);
        LoadDataByThread();
    }


 private void LoadDataByThread()
        {
            new Thread(() =>
                           {
                               new Thread(() =>
                               {
                                   lock (Locker)
                                   {
                                       _priceA = _service.GetPriceA();
                                   }
                                   _waithandle[0].Set();
                               }).Start();

                               new Thread(() =>
                               {
                                   lock (Locker)
                                   {
                                       _priceB = _service.GetPriceB();
                                   }
                                   _waithandle[1].Set();
                               }).Start();

                               WaitHandle.WaitAll(_waithandle);
                               PriceA = _priceA;
                               PriceB = _priceB;
                           }).Start();
        }

ありがとう


15
私の知る限りでは、静的は通常、インスタンスにとらわれないようにするために使用されます。「MyWorkerClass」のインスタンスが複数存在する場合、指定されたデータを使用して同時に実行できるのは1つだけです(すべてが共有リソースを使用している場合)。
ブラッドクリスティー

2
編集には重要な詳細が欠けています:どこにあり_service、どこにあり_waithandleますか?インスタンス?静的?その他?これ、たとえば、リモートサーバーへのアクセスを意図的に同期させている可能性があります...
Marc Gravell

右、2番目の編集:はい、これで、インスタンスごとにロックできます。ただし、静的にする理由があった可能性があります-元の開発者が(前述のように)アクセスを同期して、サーバーがこのAppDomainから一度に1つの要求のみを取得するようにしたい場合... 、またはそれが偶然だったかどうか。
Marc Gravell

回答:


177

「マルチスレッドでのロックにプライベート静的読み取り専用オブジェクトを使用することは非常に一般的」ではなく、適切な/選択した粒度でロックを使用するのが一般的です。時々それはstaticです。多くの場合、IMOはそうではありませんが、インスタンスベースです。

staticロックが表示される主な時間は、グローバルキャッシュ、またはグローバルデータ/シングルトンの遅延ロードです。後者の場合、とにかくそれを行うより良い方法があります

したがって、それは本当に依存Lockerします。シナリオでどのように使用されますか?それ自体が静的なものを保護していますか?その場合、ロックは静的でなければなりません。インスタンスベースの何かを保護している場合、IMOロックインスタンスベースである必要があります。


24
グローバルデータの読み込みを延期するより良い方法について詳しく説明していただけますか?
bizi 2013

インスタンスベースの場所がいくつかある場合でも、スレッドセーフな方法でアクセスされるメソッド/変数を制御したいので、私は常にstatic / volatileを使用します。多くのインスタンスが同じリソースにアクセスしている可能性があり、それを制御したいと考えています。私もこれを行う方が良いと思います。あなたには素晴らしい担当者がいて、あなたの返事も私が採用するのと同じくらい素晴らしいものになると確信しています。返信してください?
Andrew Simpson

82

静的である必要はありません。実際、静的である必要はありません。

変数は、ロックに使用するメソッドと同じスコープ内に存在する必要があります。メソッドが静的である場合、変数は静的である必要があり、メソッドがインスタンスメソッドである場合、変数はインスタンス変数である必要があります。

静的変数は、インスタンスメソッドでロックするために使用された場合でも機能しますが、ロックしすぎます。同じインスタンスのメソッドだけでなく、すべてのインスタンスのすべてのメソッドをロックします。


28
"a-ha"の+1 ... 同じインスタンスのメソッドだけでなく、すべてのインスタンスのすべてのメソッドをロックします。
レーダーボブ

3
@radarbob-細かい詳細:すべてのメソッドロックするわけではありません。ロックを取得するだけで、より多くのクライアントが関心を持つ可能性があります。メソッドはロックされず、ミューテックスが取得されただけです。
Erno 2014

私はこの答えの言い回しが誤解を招く可能性があると思います-ロックはメソッドのスコープで何もする必要はありません-それはそれらのメソッドでアクセスされる共有データのスコープにのみ関係するべきです インスタンスメソッドは、共有データにアクセスできず(したがってロックする必要もありません)、静的共有データにアクセスできます(したがって、静的ロックが必要です。代わりにリファクタリングも良い考えです)。静的と同じ...
Alexei Levenkov

@AlexeiLevenkov:データの静的かどうかによってスコープが実際に決定されるのは正しいですが、メソッドのスコープもそれによって決定される必要があるため、すべてが一致します。通常、インスタンスデータはロックする必要はありませんが、インスタンスがスレッド間で共有されている場合は、ロックする必要があります。
Guffa

28

ロックの範囲と有効期間は、ロックする「もの」に依存する場合があります。静的ロックは、主に静的なものをロックするために使用されます。


3
細部:ロックは静的ではなく、ロックの識別に使用するオブジェクトは静的です。もう1つの細かい詳細:「もの」をロックしません。
Guffa 14

2
はい、間違った「もの」を閉じ込めようとすると、大きすぎて強すぎ​​て、いつの日か逃げることができると思います。
ProfK、2015年

12
@Guffa奇妙なことに、上のコメントで正しく言ったのは、「あなたはただ物事を複雑にしすぎている」と言った1分前に、あなたは物事が複雑すぎたようです:)
Nicholas Petersen
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.