web-dev-qa-db-ja.com

手動ロックと同期方法の違い

これには何か違いがありますか?

internal class MyClass
{
    private readonly object _syncRoot = new Object();

    public void DoSomething() 
    {
        lock(_syncRoot)
        {
            ...
        }
    }

    public void DoSomethingElse() 
    {
        lock(_syncRoot)
        {
            ...
        }
    }
}

この:

internal class MyClass
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    public void DoSomething() 
    {
        ...
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void DoSomethingElse() 
    {
        ...
    }
}

私が見る唯一の違いは、最初のアプローチがいくつかのプライベートメンバーをロックするのに対して、2番目のアプローチはインスタンス自体をロックすることです(したがって、インスタンス内の他のすべてをロックする必要があります)。どのアプローチを使用するのが一般的なアドバイスですか?現在、私たちのプロジェクトには、それぞれ異なるアプローチで書かれた同様の目的を持つ2つのクラスがあります。

編集:

おそらくもう1つの質問です。これは:

internal class MyClass
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    public void DoSomething() 
    {
        ...
    }
}

このようにまったく同じ:

internal class MyClass
{
    public void DoSomething() 
    {
        lock(this) 
        {
            ...
        }
    }
}
54
Ladislav Mrnka

_syncRootをプライベートにすることができる(そしてする必要がある)ため、最初の方法が推奨されます。これにより、デッドロックのリスクが低下します。

_MethodImplOptions.Synchronized_は、それほど良くないことが判明した以前の野心的なアイデアからの残り物です。

最後の質問について:はい、 このブログ によると、機能的には同等です(ただし、同じ方法で実装されていません)。また、すべての形式のlock(this)は、デッドロックシナリオのために推奨されていません。

38
Henk Holterman

http://blogs.msdn.com/b/bclteam/archive/2004/01/20/60719.aspx および http://www.experts-exchange.com /Programming/Languages/C_Sharp/Q_20926988.html
彼らはlock(this)についても議論し、以下を使用することを勧めません。

完全に無関係なコードは、そのオブジェクトをロックすることもできます

EEからの引用:

オブジェクトをロックすると、この特定のオブジェクトにアクセスする必要がある他のすべてのスレッドは、他のオブジェクトが終了するまで待機します。ただし、メソッドを同期済みとしてマークすると、この特定のメソッドは複数のスレッドで実行されません。 Lockはオブジェクトを保護し、Synchronizedはメソッドを保護します。

13
Kamyar

ちょっと見てみると、ポータブルデバイスはMethodImplOptions.Synchronizedをサポートしていないことがわかりました。

発言もあります:

Synchronizedフラグと同様に、インスタンスまたはタイプのロックはパブリックタイプには推奨されません。これは、独自のコード以外のコードがパブリックタイプおよびインスタンスをロックする可能性があるためです。これにより、デッドロックまたはその他の同期の問題が発生する場合があります。

ソース: http://msdn.Microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions%28v=VS.100%29.aspx

8
Wojtek Turowicz

違いは、装飾されたメソッドで参照されているオブジェクトに依存すると思います。私が読んだことから、装飾は実際にILのlock()を実装しています。

最適なアプローチは、必要に応じて最も具体的なロックを行うことです。

2
Steve Mallory

この記事はあなたを助けるかもしれません: http://www.yoda.arachsys.com/csharp/threads/lockchoice.shtml

一般に、プライベートロック変数としての「this」のロックを回避すると、より適切な制御が提供されます。カスタムコレクションクラスの場合は、「これ」をロックすることをお勧めします。これが必要な場合は、SyncRootの行に沿って何かをロックします。

ハサナイン

1
Hasanain