vb.Net マルチスレッドの質問:
違いは何ですか
SyncLock syncRoot
''# Do Stuff
End SyncLock
-と-
SyncLock Me
''# Do Stuff
End SyncLock
vb.Net マルチスレッドの質問:
違いは何ですか
SyncLock syncRoot
''# Do Stuff
End SyncLock
-と-
SyncLock Me
''# Do Stuff
End SyncLock
ブロック内で発生するすべてのコードは、同じオブジェクトのブロックSyncLock
内で発生する他のすべてのコードと同期されます。明らかに、はと同じではありません(つまり、あなたがである場合、私は仮定しています)。SyncLock
Me
syncRoot
Me.SyncRoot
Me
ICollection
あるオブジェクトのブロック内で発生するコードは、別のオブジェクトのブロック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
上記Add
とRemove
呼び出しは、どのような方法、形、形式でも同期されていません。したがって、上記のコードにはスレッドセーフはありません。
さて、なぜ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
です。コレクションの変更/列挙を同期できる共通のオブジェクトを提供することを目的とするオブジェクトを提供します。他の方法でコレクションを含むコード(ただし、コレクションのコンテンツを変更または読み取るコードと同期する必要はありません)は、必要に応じて、別のオブジェクトで同期する必要があります。
なら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
つまり、同じオブジェクトを使用して保護されているコードは、効果的にシリアル化されます。
さまざまなオブジェクトをロックしています。
コード(または内部コード)の他の部分がで同期するSyncRoot
場合は、で同期することで問題が発生します(つまり、スレッドのバグが発生します)Me
。
あなたは間違いなく同期する必要SyncRoot
があります-それがそこにある理由です。