2010-05-18 6 views

Antwort

5

Alle Code, der innerhalb eines SyncLock Block geschieht mit allen anderen Code geschieht innerhalb eines SyncLock Block auf demselben Objekt synchronisiert. Offensichtlich ist Me nicht dasselbe wie syncRoot (was ist, ich nehme an, Me.SyncRoot, wenn Ihr Me ein ICollection ist).

Code, der innerhalb eines SyncLock Blocks auf einem Objekt auftritt, wird nicht mit Code innerhalb eines SyncLock Blocks auf einem anderen Objekt synchronisiert.

Sagen Sie bitte diesen Code haben:

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

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

Die oben ist in Ordnung: die Add und Remove Anrufe synchronisiert sind, das heißt, sie nicht gleichzeitig auftreten wird (je nachdem, was zuerst ausführen wird aufgerufen wird, und die zweite wird nicht ausgeführt bis der erste fertig ist).

Aber nehmen Sie diese stattdessen hatte:

' 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 

Die oben Add und Remove Anrufe sind nicht in jeder Hinsicht, Form synchronisiert oder Form. Daher gibt es keine Fadensicherheit in dem obigen Code.

Nun, warum gibt es SyncRoot? Ganz einfach, weil es Sinn macht, auf der kleinsten Skala zu synchronisieren; es besteht keine Notwendigkeit, Code zu synchronisieren, der nicht tatsächlich synchronisiert werden muss.

Betrachten Sie dieses Beispiel:

' 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 

Im obigen Sie mehr als nötig synchronisieren. Der Add Aufruf hat wirklich nichts mit der Umbenennung des myColl Objekts zu tun; Daher muss der Code nicht synchronisiert werden.

Dies ist die Idee hinter der SyncRoot-Eigenschaft: Sie gibt Ihnen ein Objekt, dessen gesamter Zweck es ist, ein gemeinsames Objekt bereitzustellen, mit dem Änderungen an/Aufzählungen der Auflistung synchronisiert werden können.Code umfasst die Sammlung in einigen anderen Weg - aber die nicht mit Code synchronisiert werden muss, der den Inhalt der Sammlung ändert oder liest - sollte gegebenenfalls auf ein anderes Objekt synchronisiert werden.

2

Sie auf verschiedene Objekte sperren.

Wenn andere Teile Ihres Codes (oder internen Codes) auf SyncRoot synchronisieren, was sie sollten, dann brechen Sie Dinge (d. H. Das Einführen von Threading-Bugs) durch die Synchronisierung auf Me.

Sie sollten unbedingt auf SyncRoot synchronisieren - deshalb ist es da.

+0

Ich bin ein wenig verwirrt über SyncLock. Verhindert synclock Änderungen an der Variablen, die ich an sie übergebe (in diesem Fall 'syncRoot'), oder sperrt sie einfach den Code? –

3

Wenn Object.ReferenceEquals(syncRoot, Me) = True dann nichts anderes ist. Andernfalls wird die Sperre mit verschiedenen Objekten erfasst.

Wenn Ihre Verwendung von syncRoot äquivalent zu ICollection.SyncRoot ist, wird die Sperre mit demselben Objekt erfasst, das intern von der Sammlung für ihre eigene Sperrung verwendet wird. Auf diese Weise können Sie den Zugriff auf Enumeratoren synchronisieren. Zum Beispiel:

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

Als eine Frage der Konvention .NET-Entwickler nicht zu verwenden Me als das Verriegelungsobjekt. Dies gilt insbesondere dann, wenn Me als Objekt referenziert, das für die öffentliche API einer Klassenbibliothek sichtbar ist. Der Grund, warum wir dies vermeiden, ist, dass anderer Code möglicherweise dasselbe Objekt verwendet, um eine Sperre zu erhalten, und zwar aus einem Grund, der mit dem semantischen Verhalten kollidiert, das Sie in Ihrem Code erreichen wollen. Dieser Konflikt kann zu Engpässen oder sogar Deadlocks führen.

Es sollte beachtet werden, dass SyncLock nicht den Zugriff auf das Sperrobjekt selbst synchronisiert, sondern den Code, der durch das SyncLock Konstrukt eingewickelt wird. Mit anderen Worten, Code, der von einem SyncLock mit demselben Objekt geschützt wird, wird effektiv serialisiert.

+0

Mir ist gerade aufgefallen, dass das Wort "using" im 2. Absatz 1. Satz hintereinander erscheint. In der Textbox des Inhalts-Editors wird dies nicht angezeigt. Fehler in SO? –

Verwandte Themen