2009-05-23 1 views
5

Könnte mir jemand die Synchronisation der Bedingungen erklären?Was ist Konditionssynchronisation?

Ein Beispiel (vorzugsweise in C#) würde auch sehr geschätzt werden.

+1

Ich habe von "Synchronisation" gehört: es ist in der Regel eine Phrase im Zusammenhang mit Multi-Threading, speziell mit verschiedenen Arten von "Sperre", die erforderlich sein kann, um die Threads zu "synchronisieren", um den Code "thread-safe" ". Aber ich weiß nicht speziell "* Bedingung * Synchronisation". – ChrisW

Antwort

8

Es klingt wie Ihr Professor über Threading spricht. Durch das Threading können Computerprogramme mehr als eine Sache gleichzeitig ausführen. Der Vorgang des Startens eines neuen Threads, während einer bereits ausgeführt wird, wird von Computerprogrammierern als "Hochdrehen eines Threads" bezeichnet.

Threads können denselben Speicherplatz teilen. Condition Synchronization (oder nur Synchronisation) ist ein Mechanismus, der verhindert, dass Speicherbereiche gleichzeitig von zwei verschiedenen Threads geändert werden.

Nehmen wir an, Sie sind einkaufen, und die Frau ist zu Hause, um die Rechnungen zu bezahlen. Dies ist ein naives Beispiel, und im wirklichen Leben funktioniert das nicht so, aber es wird als einfache Illustration dienen.

Ihre Frau bezahlt eine Rechnung online. Gleichzeitig wischen Sie Ihre Kreditkarte im Supermarkt. Bei beiden Handlungen müssen Sie Geld von Ihrem Girokonto abheben. Um diese Aktivität zu simulieren wir den folgenden Code schreiben:

public class MyBanking 
{ 
    static double myAccountBalance; 
    // 
    public void DebitAccount(double debitAmount) 
    { 
     Console.Writeline("Your Old Balance is: " + myAccountBalance.ToString()); 
     Console.Writeline("Your Debit is:  " + debitAmount.ToString()); 
     myAccountBalance = myAccountBalance - amount; 
     Console.Writeline("Your New Balance is: " + myAccountBalance.ToString()); 
    } 
} 

Hypothetisch, Ihre Frau läuft eine Instanz („copy“) dieser Klasse in einem Thread, Sie ausführen, eine Instanz auf einem anderen Thread. Die Variable myAccountBalance wird als statisch deklariert, damit sie von beiden aktiven Instanzen gemeinsam genutzt werden kann (Sie und Ihre Frau haben nur ein Girokonto).

Sie Ihre Debit machen, indem Sie den Code wie folgt aufrufen:

MyBanking bankingObject = new MyBanking(); 
bankingObject.DebitAccount(100); 

Ihre Frau macht ihre Debit zugleich:

MyBanking bankingObject = new MyBanking(); 
bankingObject.DebitAccount(50); 

Was passiert, wenn der Thread geschieht durch Ihre Frau Thread unterbrochen wird nachdem Ihr altes Guthaben auf dem Bildschirm gedruckt wurde, aber bevor das neue Guthaben gedruckt wird? Der Thread Ihrer Frau belastet den Account und gibt die Kontrolle an Ihren Thread zurück.Ihre Frau sieht diese auf dem Bildschirm:

Your Old Balance is: 2000 
Your Debit is:  50 
Your New Balance Is: 1950 

Wenn der Computer druckt das neue Gleichgewicht auf dem Bildschirm, ist es falsch sein, weil Ihre Frau Abbuchungs auch gezählt wurde, werden. Sie werden so etwas sehen:

Your Old Balance is: 2000 
Your Debit is:  100 
Your New Balance Is: 1850 

Um dies zu beheben, umgeben wir unseren Methodencode mit einer Lock-Anweisung. Die Sperranweisung bewirkt, dass alle anderen Threads auf den Abschluss unserer Instanz warten. Der neue Code sieht wie folgt aus:

public class MyBanking 
{ 
    static double myAccountBalance; 
    // 
    public void DebitAccount(double debitAmount) 
    { 
     lock (this) 
     { 
      Console.Writeline("Your Old Balance is: " + myAccountBalance.ToString()); 
      Console.Writeline("Your Debit is:  " + debitAmount.ToString()); 
      myAccountBalance = myAccountBalance - amount; 
      Console.Writeline("Your New Balance is: " + myAccountBalance.ToString()); 
     } 
    } 
} 

Thread Ihre Frau jetzt Ihren Code innerhalb der lock-Anweisung warten zu beenden ausgeführt wird, bevor der Code Ihrer Frau beginnt mit der Ausführung. Ihr neuer Kontostand ist nun korrekt, da es nicht mehr möglich ist, dass der Thread Ihrer Frau das Guthaben ändert, während Sie IHRE Transaktion abschließen. Auf dem Bildschirm sehen Sie jetzt sehen:

Your Old Balance is: 2000 
Your Debit is:  100 
Your New Balance Is: 1900 

Ihre Frau dies sehen:

Your Old Balance is: 1900 
Your Debit is:  50 
Your New Balance Is: 1850 

Dies ist die Synchronisation.

+0

Es gibt auch etwas, das eine bedingte Variable genannt wird. Siehe diesen Artikel für Details: http://en.wikipedia.org/wiki/Monitor_%28synchronization%29 –

+0

Frau hat falsche Ausgabe. 1900 - 50! = 1800 –

+0

@IgorGorjanc: Danke. –

2

Im Grunde ist es ein Design-Muster für Threads, die brauchen

a) synchronisieren Zugriff auf eine Ressource

b) manchmal für andere Threads warten, bis eine bestimmte Voraussetzungen erfüllt ist

Sie diese in eine frage C# -Kontext, .NET unterstützt dies mit Monitor.Wait und Monitor.Pulse (und mit Wrappern um verschiedene Win32-Objekte wie WaitEventhandle).

Hier ist eine nette queue example auf SO.

Die wichtigsten technischen Details wie folgt aussehen:

lock(buffer) // is Monitor.Enter(buffer) ... finally Monitor.Leave(buffer) 
{ 
    while (buffer.Count < 1) 
    { 
     Monitor.Wait(buffer); 
    } 
    ... 
} 

Beachten Sie, wie ein dort Wait-while-gesperrt ist. Es sieht aus wie ein Deadlock, aber Wait wird das Schloss freigeben, während es wartet. Der Code in der lock() { } hat weiterhin exklusiven Zugriff auf Puffer, wenn es ausgeführt wird.

Und dann hat ein anderer Thread zu signalisieren, wenn es etwas in den Puffer legt:

Monitor.Pulse(buffer); 
1

Der obige Code ist fast korrekt, ist aber eigentlich falsch. Wenn Sie verwenden, sperren Sie nur Ihre Instanz der Klasse MyBanking, aber Ihre Frau wird ihre sperren. So sperren Sie den Zugriff auf die gemeinsam genutzte Variable können Sie entweder den Typ verriegeln (dh lock(typeof(MyBanking))) oder Sie können eine neue gemeinsame Variable einführen und verriegeln, dass (Sie können nicht einen int sperren, so typischerweise Menschen zu schaffen, ein Objekt wie folgt.

class MyBanking 
{ 
    static object lockObj = new object(); 
    static double myAccountBalance; 
    public void DebitAccount(double debitAmount) 
    { 
     lock (lockObj) 
1

Synchronization bereits deutlich erklärt worden. jedoch diktiert Bedingung Synchronisations spezifisch, dass ein Prozess/Thread nur ausführt, nachdem eine Bedingung. Typischerweise erfüllt wird, wird die Bedingung sein, dass ein anderer Prozess/Thread bereits ausgeführt hat.

Im angegebenen Beispiel für die Belastung eines Kontos und die Anzeige des Guthabens. Wenn die Anzeige Ihres Guthabens eine separate synchronisierte Methode war und wir das Guthaben nur anzeigen wollten, nachdem Ihr Konto abgebucht wurde, würde dies eine Konditionssynchronisierung erfordern.

Bedingung Synchronisation ist sehr gut von der producer-consumer problem beschrieben.