Frage

Ich habe eine einfache Producer / Consumer-Szenario, in dem es immer nur ein einzelnes Element wird produziert / verbraucht. Außerdem wartet der Hersteller für den Worker-Thread zu beenden, bevor Sie fortfahren. Ich ist klar, dass Art umgeht den ganzen Sinn des Multithreading, aber bitte nur annehmen, dass es wirklich so sein muss (:

Dieser Code nicht kompilieren, aber ich hoffe, Sie bekommen die Idee:

// m_data is initially null

// This could be called by any number of producer threads simultaneously
void SetData(object foo)
{
    lock(x)                      // Line A
    {
        assert(m_data == null);
        m_data = foo;
        Monitor.Pulse(x)         // Line B
        while(m_data != null)
            Monitor.Wait(x)      // Line C
    }
}

// This is only ever called by a single worker thread
void UseData()
{
    lock(x)                      // Line D
    {
        while(m_data == null)
            Monitor.Wait(x)      // Line E
        // here, do something with m_data
        m_data = null;
        Monitor.Pulse(x)         // Line F
    }
}

Hier ist die Situation, dass ich bin nicht sicher:

Es seien viele Threads nennen SetData () mit verschiedenen Eingängen. Nur einer von ihnen wird innerhalb des Schlosses erhalten, und der Rest der Linie A blockiert werden Angenommen, die eine, die in den Schloss-Sets bekam m_Data und macht seinen Weg in der Linie C.

Frage: Könnte die Wait () auf der Linie C ermöglicht ein anderer Thread auf Linie A die Sperre und Überschreiben m_Data zu erhalten, bevor der Arbeiter-Thread bekommt sogar, um es

?

Angenommen, die nicht passieren, und der Arbeiter-Thread verarbeitet die ursprüngliche m_Data , und macht schließlich seinen Weg in der Linie F, was passiert, wenn das Pulse () erlischt?

Wird nur der Thread wartet auf die Linie C der Lage sein, um die Sperre zu bekommen? Oder wird es auch mit allen anderen Threads warten auf der Linie A konkurrieren?

Im Grunde möchte ich wissen, ob Pulse () / Wait () miteinander kommunizieren, speziell „unter der Haube“ oder wenn sie auf dem gleichen Niveau sind mit Schloss ().

Die Lösung für diese Probleme, wenn sie vorhanden sind, liegt auf der Hand natürlich - nur Surround SetData () mit einem anderen Schloss - sagen wir, Schloss (y). Ich bin nur neugierig, wenn es einmal ein Problem zu beginnen.

War es hilfreich?

Lösung

Es gibt keine Garantie, dass der Verbraucher auf der Warte oder Bereitschafts-Warteschlange, bevor ein anderer Hersteller die Warteschlange gestellt wird.
C # und Java-Stil-Monitore sind beschrieben auf Wikipedia unter "Implicit Bedingung Monitore" .
Ein schöner Überblick darüber, was passiert, in Monitor (aus dieser ausgezeichneten Website): alt text

  

„Könnte die Wait () auf der Linie C ermöglichen ein anderer Thread auf Linie A das Schloss und Überschreiben m_Data vor dem Arbeitsthread zu erhalten kommt noch dazu?“

Nehmen wir an, dass SetData() wird von zwei Produzenten-Threads genannt, P1 & P2 .
Ein Verbraucher-Thread, C1 wird gestartet als auch.
P1 , P2 und C1 alle geben Sie die Bereitschafts-Warteschlange.
P1 erwirbt das Schloss zuerst.
Die Warteschlange leer ist, Pulse() auf line B hat keine Wirkung.
P1 wartet auf line C, so dass es auf die Warteschlange gestellt wird.
Der nächste Thread in der Bereitschaftswarteschlange erwirbt das Schloss.
Ebenso kann es sein P2 oder C1 - im ersten Fall die Behauptung versagt
. Sie haben eine Race-Bedingung.

  

„Annahme, dass nicht passiert, und der Arbeiter-Thread verarbeitet die ursprüngliche m_Data, und macht schließlich seinen Weg in der Linie F, was passiert, wenn das Pulse () erlischt?“

Es wird einen Kellner aus der Warteschlange zu der Bereitschaftswarteschlange bewegen.
Die Sperre wird durch das Gewinde gehalten, dass Fragen der Pulse().
Der benannte Thread die Chance bekommen, die Sperre nach den pulsierenden Thread Versionen erwerben die Sperre (es kann schon andere in der Bereitschaftswarteschlange sein).
Aus MSDN, Monitor .Pulse () :
"Der Faden, dass zur Zeit besitzt die Sperre für das angegebene Objekt ruft diese Methode auf den nächsten Thread in der Linie für das Schloss zu signalisieren. Bei dem Impulse empfängt, der wartende Thread auf die Bereitschafts-Warteschlange bewegt wird. Wenn der Faden, der aufgerufen Pulse die Sperre, der nächsten Thread in der Bereitschaftswarteschlange (die nicht unbedingt das Gewinde, das wurde gepulst) die Sperre erwirbt. "

  

„Wird nur der Thread wartet auf die Linie C der Lage sein, um die Sperre zu bekommen? Oder wird es mit allen anderen Threads warten auf der Linie A als auch konkurrieren?“

Alle Themen, die auf der Bereitschaftswarteschlange „konkurrieren“ sind für das Schloss nächsten ist.
Es spielt keine Rolle, ob sie dorthin gekommen sind gerade oder aus der Warteschlange mittels Pulse().

Die „Warteschlangen“ könnte mit anderen Mitteln realisiert werden. (Nicht die Warteschlange Datenstruktur als solche).
Auf diese Weise eine Monitor Implementierung Fairness nicht garantieren kann - aber möglicherweise höheren Gesamtdurchsatz / Leistung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top