¿Cómo puedo sincronizar tres hilos?

Mi aplicación consta del proceso principal y dos subprocesos, todos ejecutándose simultáneamente y haciendo uso de tres quince colas:

Los fifo-q son Qmain, Q1 y Q2. Internamente, cada una de las colas utiliza un contador que se incrementa cuando un elemento se coloca en la cola y disminuye cuando un elemento se 'obtiene' de la cola.

El procesamiento involucra dos hilos,
QMaster, que obtiene de Q1 y Q2, y se coloca en Qmain,
Monitor, que se puso en Q2,
y el proceso principal, que se obtiene de Qmain y se coloca en Q1.

El bucle QMaster-thread verifica consecutivamente los recuentos de Q1 y Q2 y, si hay elementos en las q, los obtiene y los coloca en Qmain.

El bucle Monitor-thread obtiene datos de fuentes externas, los empaqueta y los coloca en Q2.

El proceso principal de la aplicación también ejecuta un ciclo que verifica el recuento de Qmain, y si hay algún elemento, obtiene un elemento de Qmain en cada iteración del ciclo y lo procesa aún más. Durante este procesamiento, ocasionalmente coloca un elemento en Q1 para procesarlo más tarde (cuando Qmain lo obtiene a su vez).

El problema:
He implementado todo como se describió anteriormente, y funciona durante un tiempo aleatorio (corto) y luego se bloquea. Me las arreglé para identificar la fuente del bloqueo que ocurriría en el incremento / decremento del conteo de un fifo-q (puede ocurrir en cualquiera de ellos).

Lo que probé:
Usando tres mutex: QMAIN_LOCK, Q1_LOCK y Q2_LOCK, que bloqueo cada vez que se realiza una operación get / put en un fifo-q relevante. Resultado: la aplicación no funciona, solo se cuelga.

El proceso principal debe continuar ejecutándose todo el tiempo, no debe bloquearse en una 'lectura' (fallan las canalizaciones con nombre, falla del par de sockets).

¿Algún consejo?
Creo que no estoy implementando los mutex correctamente, ¿cómo debería hacerse?
(Cualquier comentario sobre la mejora del diseño anterior también es bienvenido)

[editar] a continuación están los procesos y la plantilla fifo-q:
¿Dónde y cómo debo colocar los mutex para evitar los problemas descritos anteriormente?

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() {...}
};

Respuestas a la pregunta(6)

Su respuesta a la pregunta