5

vb.Net マルチスレッドの質問:

違いは何ですか

SyncLock syncRoot  
  ''# Do Stuff  
End SyncLock

-と-

SyncLock Me  
  ''# Do Stuff  
End SyncLock
4

3 に答える 3

5

ブロック内で発生するすべてのコードは、同じオブジェクトのブロックSyncLock内で発生する他のすべてのコードと同期されます。明らかに、はと同じではありません(つまり、あなたがである場合、私は仮定しています)。SyncLockMesyncRootMe.SyncRootMeICollection

あるオブジェクトのブロック内で発生するコードは、別のオブジェクトのブロックSyncLock内のコードと同期されませんSyncLock

あなたがこのコードを持っているとしましょう:

' happening on thread 1 '
SyncLock myColl.SyncRoot
    myColl.Add(myObject)
End SyncLock

' happening on thread 2 '
SyncLock myColl.SyncRoot
    myColl.Remove(myObject)
End SyncLock

上記は問題ありません。AddとのRemove呼び出しは同期されます。つまり、同時に発生することはありません(最初に呼び出された方が実行され、最初の呼び出しが終了するまで2番目の呼び出しは実行されません)。

しかし、代わりにこれを持っていたとしましょう:

' happening on thread 1 '
SyncLock myColl.SyncRoot
    myColl.Add(myObject)
End SyncLock

' happening on thread 2 '
SyncLock myColl ' NOTE: SyncLock on a different object '
    myColl.Remove(myObject)
End SyncLock

上記AddRemove呼び出しは、どのような方法、形、形式でも同期されていません。したがって、上記のコードにはスレッドセーフはありません。

さて、なぜSyncRoot存在するのですか?非常に簡単です。必要な最小スケールで同期することが理にかなっているからです。つまり、実際に同期する必要のないコードを同期する必要はありません。

この例を考えてみましょう。

' happening on thread 1 '
SyncLock myColl
    myColl.Add(myObject)
End SyncLock

' happening on thread 2 '
SyncLock myColl
    ' Why you would have code like this, I do not know; '
    ' this is just for illustration. '
    myColl.Name = myColl.Name.Replace("Joe", "Bill")
End SyncLock

' happening on thread 3 '
SyncLock myColl
    myColl.Name = myColl.Name.Replace("Bill", "Joe")
End SyncLock

上記では、必要以上に同期しています。この呼び出しは、実際にはオブジェクトAddの名前変更とは何の関係もありません。myCollしたがって、コードを同期する必要はありません。

これは、プロパティの背後にある考え方SyncRootです。コレクションの変更/列挙を同期できる共通のオブジェクトを提供することを目的とするオブジェクトを提供します。他の方法でコレクションを含むコード(ただし、コレクションのコンテンツを変更または読み取るコードと同期する必要はありません)は、必要に応じて、別のオブジェクトで同期する必要があります。

于 2010-05-18T15:13:03.847 に答える
3

ならObject.ReferenceEquals(syncRoot, Me) = True何も変わらない。それ以外の場合、ロックは別のオブジェクトを使用して取得されます。

の使用がsyncRootと同等である場合ICollection.SyncRoot、コレクションが独自のロックのために内部で使用するのと同じオブジェクトを使用してロックが取得されます。これにより、列挙子へのアクセスを同期できます。例えば:

SyncLock collection.SyncRoot
  For Each item As Object in collection
  Next
End SyncLock

慣例として、.NET 開発者Meはロック オブジェクトとしての使用を避けます。Meこれは、クラス ライブラリのパブリック API に表示されるオブジェクトとして参照する場合に特に当てはまります。これを回避する理由は、他のコードが同じオブジェクトを使用してロックを取得する可能性があるためです。これは、コードで達成しようとしているセマンティックな動作と競合するためです。この競合は、ボトルネックやデッドロックにつながる可能性があります。

SyncLockはロック オブジェクト自体へのアクセスを同期するのではなく、SyncLockコンストラクトによってラップされたコードを同期することに注意してください。SyncLockつまり、同じオブジェクトを使用して保護されているコードは、効果的にシリアル化されます。

于 2010-05-18T15:22:53.603 に答える
2

さまざまなオブジェクトをロックしています。

コード(または内部コード)の他の部分がで同期するSyncRoot場合は、で同期することで問題が発生します(つまり、スレッドのバグが発生します)Me

あなたは間違いなく同期する必要SyncRootがあります-それがそこにある理由です。

于 2010-05-18T15:12:35.953 に答える