Wie kann ich drei Threads synchronisieren?

Meine App besteht aus dem Hauptprozess und zwei Threads, die alle gleichzeitig ausgeführt werden und drei FIFO-Warteschlangen verwenden:

Die fifo-q sind Qmain, Q1 und Q2. Intern verwenden die Warteschlangen jeweils einen Zähler, der erhöht wird, wenn ein Element in die Warteschlange gestellt wird, und verringert wird, wenn ein Element aus der Warteschlange abgerufen wird.

Die Verarbeitung umfasst zwei Threads,
QMaster, das aus Q1 und Q2 stammt und in Qmain gestellt wird,
Monitor, der in Q2 steckte,
und der Hauptprozess, der von Qmain kommt und in Q1 gestellt wird.


Die QMaster-Thread-Schleife überprüft nacheinander die Anzahl von Q1 und Q2. Wenn sich Elemente in den Qs befinden, werden sie abgerufen und in Qmain abgelegt.

Die Monitor-Thread-Schleife ruft Daten von externen Quellen ab, packt sie und fügt sie in Q2 ein.

Der Hauptprozess der App führt auch eine Schleife aus, in der die Anzahl von Qmain überprüft wird. Wenn Elemente vorhanden sind, wird bei jeder Iteration der Schleife ein Element von Qmain abgerufen und weiterverarbeitet. Während dieser Verarbeitung wird gelegentlich ein Artikel in Q1 abgelegt, der später verarbeitet werden soll (wenn er wiederum von Qmain abgerufen wird).

Das Problem
Ich habe alles wie oben beschrieben implementiert, und es funktioniert für eine zufällige (kurze) Zeit und hängt dann. Ich habe es geschafft, die Ursache des Absturzes zu identifizieren, indem ich die Zählung eines Fifo-Q inkrementierte / dekrementierte (es kann in jedem von ihnen vorkommen).

Was ich versucht habe:
Verwenden Sie drei Mutexe: QMAIN_LOCK, Q1_LOCK und Q2_LOCK, die ich sperre, wenn eine Get / Put-Operation für ein relevantes FIFO-Q ausgeführt wird. Ergebnis: Die App startet nicht, hängt nur.

Der Hauptprozess muss die ganze Zeit weiterlaufen, darf beim 'Lesen' nicht blockiert werden (Named Pipes scheitern, Socketpaar scheitert).

Irgendein Rat
Ich denke, ich implementiere die Mutexe nicht richtig, wie soll es gemacht werden?
(Kommentare zur Verbesserung des obigen Designs sind ebenfalls willkommen)

[edit] unten sind die Prozesse und das Fifo-Q-Template:
Wo und wie soll ich die Mutexe platzieren, um die oben beschriebenen Probleme zu vermeiden?

main-process:
...
start thread QMaster
start thread Monitor
...
while (!quit)
{
    ...
    if (Qmain.count() > 0)
    {
        X = Qmain.get();
        process(X) 
            delete X;
    }
    ...
    //at some random time:
    Q2.put(Y);
    ...
}

Monitor:
{
    while (1)
    {
        //obtain & package data
        Q2.put(data)
    }
}

QMaster:
{
    while(1)
    {
        if (Q1.count() > 0)
            Qmain.put(Q1.get());

        if (Q2.count() > 0)
            Qmain.put(Q2.get());
    }
}

fifo_q:
template < class X* > class fifo_q
{
    struct item
    {
        X* data;
        item *next;
        item() { data=NULL; next=NULL; }
    }
    item *head, *tail;
    int count;
public:
    fifo_q() { head=tail=NULL; count=0; }
    ~fifo_q() { clear(); /*deletes all items*/ }
    void put(X x) { item i=new item(); (... adds to tail...); count++; }
    X* get() { X *d = h.data; (...deletes head ...); count--; return d; }
    clear() {...}
};