Erstens: Die meisten Klassen müssen niemals threadsicher sein. Verwenden Sie YAGNI : Wenden Sie Thread-Sicherheit nur an, wenn Sie wissen, dass Sie es tatsächlich verwenden werden (und testen Sie es).
Für die Sachen auf Methodenebene gibt es [MethodImpl]:
[MethodImpl(MethodImplOptions.Synchronized)]
public void SomeMethod() {/* code */}
Dies kann auch für Accessoren (Eigenschaften und Ereignisse) verwendet werden:
private int i;
public int SomeProperty
{
[MethodImpl(MethodImplOptions.Synchronized)]
get { return i; }
[MethodImpl(MethodImplOptions.Synchronized)]
set { i = value; }
}
Beachten Sie, dass feldartige Ereignisse werden standardmäßig synchronisiert, während automatisch implementierte Eigenschaften sind nicht :
public int SomeProperty {get;set;} // not synchronized
public event EventHandler SomeEvent; // synchronized
Persönlich mag ich die Implementierung nicht, MethodImplda sie sperrt thisoder typeof(Foo)- was gegen Best Practice verstößt. Die bevorzugte Option ist die Verwendung eigener Schlösser:
private readonly object syncLock = new object();
public void SomeMethod() {
lock(syncLock) { /* code */ }
}
Beachten Sie, dass bei feldähnlichen Ereignissen die Sperrimplementierung vom Compiler abhängt. In älteren Microsoft-Compilern ist es ein lock(this)/ lock(Type)- in neueren Compilern werden jedochInterlocked Updates verwendet - also threadsicher ohne die unangenehmen Teile.
Dies ermöglicht eine detailliertere Verwendung und die Verwendung von Monitor.Wait/ Monitor.Pulseetc für die Kommunikation zwischen Threads.
Ein verwandter Blogeintrag (später überarbeitet ).