Ein weiteres konkretes Beispiel bauen:
class Program
{
public class Test
{
public string DoThis()
{
lock (this)
{
return "got it!";
}
}
}
public delegate string Something();
static void Main(string[] args)
{
var test = new Test();
Something call = test.DoThis;
//Holding lock from _outside_ the class
IAsyncResult async;
lock (test)
{
//Calling method on another thread.
async = call.BeginInvoke(null, null);
}
async.AsyncWaitHandle.WaitOne();
string result = call.EndInvoke(async);
lock (test)
{
async = call.BeginInvoke(null, null);
async.AsyncWaitHandle.WaitOne();
}
result = call.EndInvoke(async);
}
}
In diesem Beispiel wird der erste Anruf wird gelingen , aber wenn Sie im Debugger verfolgen, blockiert der Aufruf von DoSomething, bis die Sperre freigegeben wird. Der zweite Anruf wird Deadlock, da der Hauptfaden der Bildschirmsperre auf Test halten.
Das Problem ist, dass Main die Objektinstanz sperren kann, was bedeutet, dass es die Instanz davon abhalten kann, alles zu tun, was das Objekt für synchronisiert hält. Der Punkt ist, dass das Objekt selbst weiß, was gesperrt werden muss, und externe Störungen verlangen nur nach Ärger. Deshalb ist das Muster, das eine private Variable zu haben, die Sie ausschließlich zur Synchronisation, ohne sich um Einmischung von außen sorgen können.
Das gleiche gilt für die äquivalente statische Muster:
class Program
{
public static class Test
{
public static string DoThis()
{
lock (typeof(Test))
{
return "got it!";
}
}
}
public delegate string Something();
static void Main(string[] args)
{
Something call =Test.DoThis;
//Holding lock from _outside_ the class
IAsyncResult async;
lock (typeof(Test))
{
//Calling method on another thread.
async = call.BeginInvoke(null, null);
}
async.AsyncWaitHandle.WaitOne();
string result = call.EndInvoke(async);
lock (typeof(Test))
{
async = call.BeginInvoke(null, null);
async.AsyncWaitHandle.WaitOne();
}
result = call.EndInvoke(async);
}
}
ein eigenes statisches Objekt Verwenden Sie auf synchronisieren, nicht der Typ.
Im zweiten Beispiel ist SyncRoot() soll doThat sein()? –
"Objekt der Instanz" == "Instanz der Klasse" Schlecht geschriebenes Buch. –
Danke für die Bearbeitung Will Dean. Verdammt Kopieren/Einfügen :) – Ryan