Question

J'ai un simple producteur/consommateur scénario, où il n'y a qu'un seul élément produite/consommée.Aussi, le producteur attend que le thread de travail à terminer avant de continuer.Je me rends compte de ce type de méthode permet d'éviter le point de l'ensemble du multithreading, mais s'il vous plaît il suffit de supposer qu'il a vraiment besoin d'être de cette façon (:

Ce code ne compile pas, mais j'espère que vous avez compris l'idée:

// 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
    }
}

C'est la situation que je ne suis pas sûr à ce sujet:

Supposons que le nombre de threads appel SetData() avec des entrées différentes.Un seul d'entre eux va pénétrer à l'intérieur de la serrure, et le reste sera bloqué sur la Ligne A.Supposons que celui qui a obtenu à l'intérieur de la serrure ensembles m_data et fait son chemin à la Ligne C.

Question:Pourrait le Wait() sur la Ligne C permettre à un autre thread à la Ligne pour obtenir le verrou et remplacer m_data avant que le thread de travail encore à elle?

En supposant que cela n'arrive pas, et le thread de travail les processus de l'original m_data, et finalement fait son chemin à la Ligne F, ce qui est le cas lorsque l'Impulsion() s'éteint?

Ne le thread en attente sur la Ligne C être en mesure d'obtenir la serrure?Ou qu'il sera en concurrence avec tous les autres threads en attente sur la Ligne A ainsi?

Essentiellement, je veux savoir si d'Impulsion()/Wait() de communiquer les uns avec les autres, spécialement "sous le capot", ou si elles sont sur le même niveau avec serrure().

La solution à ces problèmes, s'ils existent, est évident, bien sûr - tout surround SetData() avec un autre lock - dire, de verrouillage(y).Je suis juste curieux de savoir si c'est encore un problème pour commencer.

Était-ce utile?

La solution

Il n'ya aucune garantie que le consommateur va être mis en file d'attente en attente ou de prêt de la file d'attente avant qu'un autre producteur.
C# et Java style moniteurs sont décrites sur Wikipédia, en vertu "d'une condition Implicite des moniteurs".
Un bel aperçu de ce qui se passe dans Monitor (prise de cette excellent site):alt text

"Le Wait() sur la Ligne C permettre à un autre thread à la Ligne pour obtenir le verrou et écraser m_data avant que le thread de travail encore à elle?"

Supposons que SetData() est appelé par deux threads producteurs, P1 & P2.
Un thread consommateur, C1 est commencé ainsi.
P1, P2 et C1 tous entrer dans la file d'attente prêt.
P1 acquiert le verrou de la première.
La file d'attente est vide, Pulse() sur line B n'a aucun effet.
P1 attend line C, de sorte qu'il est placé sur la file d'attente.
Le fil suivant dans la file d'attente prêt acquiert le verrou.
Il peut également être P2 ou C1 - dans le premier cas, l'assertion échoue.
Vous avez une race condition.

"En supposant que cela n'arrive pas, et le thread de travail les processus de l'original m_data, et finalement fait son chemin à la Ligne F, ce qui est le cas lorsque l'Impulsion() s'éteint?"

Il va se déplacer d'un serveur à partir de la file d'attente pour le prêt de la file d'attente.
Le verrou est détenu par le thread qui délivre le Pulse().
La notifié thread obtenez une chance pour acquérir le verrou après la synchronisation de thread libère le verrou (il y a peut-être déjà d'autres dans la file d'attente prêt).
À partir de MSDN, Moniteur.Pulse():
"Le fil conducteur qui possède actuellement le verrou sur l'objet spécifié appelle cette méthode pour signaler le prochain thread en ligne pour le verrouiller.Lors de la réception de l'impulsion, le thread en attente est déplacé vers la file d'attente prêt.Lorsque le thread qui a appelé Pulse libère le verrou, le fil suivant dans la file d'attente prêt (ce qui n'est pas nécessairement le thread qui a été pulsé) acquiert le verrou."

"Ne le thread en attente sur la Ligne C être en mesure d'obtenir la serrure?Ou qu'il sera en concurrence avec tous les autres threads en attente sur la Ligne A ainsi?"

Tous les threads qui sont sur la file d'attente prêt "concurrencer" pour avoir de l'écluse suivante.
Ce n'est pas grave si ils sont arrivés directement ou à partir de la file d'attente par le biais de Pulse().

Les "files d'attente" pourrait être mise en œuvre par d'autres moyens.(Pas la la file d'attente structure de données en tant que telle).
De cette façon, un Monitor la mise en œuvre ne peut pas garantir l'équité, mais peut être plus élevé, débit global/performance.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top