Como posso sincronizar três threads?

Meu aplicativo consiste no processo principal e em dois threads, todos em execução simultaneamente e utilizando três filas de quinze:

O fifo-q é Qmain, Q1 e Q2. Internamente, as filas usam um contador que é incrementado quando um item é colocado na fila e decrementado quando um item é 'obtido' da fila.

O processamento envolve dois threads,
QMaster, que sai do primeiro e segundo trimestres e é colocado no Qmain,
Monitor, colocado no Q2,
e o processo principal, que sai do Qmain e entra no primeiro trimestre.

O loop QMaster-thread verifica consecutivamente as contagens de Q1 e Q2 e, se houver algum item no q, ele recebe e coloca no Qmain.

O loop Monitor-thread obtém dados de fontes externas, empacota e coloca no Q2.

O processo principal do aplicativo também executa um loop verificando a contagem de Qmain e, se houver algum item, obtém um item do Qmain a cada iteração do loop e o processa ainda mais. Durante esse processamento, ele ocasionalmente coloca um item no primeiro trimestre para ser processado posteriormente (quando é obtido do Qmain por sua vez).

O problema:
Eu implementei tudo como descrito acima, e funciona por um tempo aleatório (curto) e depois trava. Eu consegui identificar a origem da falha no incremento / decremento da contagem de um fifo-q (isso pode acontecer em qualquer uma delas).

O que eu tentei:
Usando três mutexs: QMAIN_LOCK, Q1_LOCK e Q2_LOCK, que eu tranco sempre que qualquer operação de get / put é feita em um fifo-q relevante. Resultado: o aplicativo não funciona, apenas trava.

O processo principal deve continuar em execução o tempo todo, não deve ser bloqueado em uma 'leitura' (pipes nomeados falham, socketpair falha).

Algum conselho?
Eu acho que não estou implementando o mutex corretamente, como isso deve ser feito?
(Quaisquer comentários sobre como melhorar o design acima também são bem-vindos)

[edit] abaixo estão os processos e o fifo-q-template:
Onde e como devo colocar o mutex para evitar os problemas descritos acima?

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

questionAnswers(6)

yourAnswerToTheQuestion