Как я могу синхронизировать три потока?

Мое приложение состоит из основного процесса и двух потоков, причем все они работают одновременно и используют три очереди fifo:

FIFO-Q - это Qmain, Q1 и Q2. Внутри каждой очереди используется счетчик, который увеличивается, когда элемент помещается в очередь, и уменьшается, когда элемент «извлекается» из очереди.

Обработка включает в себя два потока,
QMaster, который получают из Q1 и Q2 и помещают в Qmain,
Монитор, который положил в Q2,
и основной процесс, который получают из Qmain и помещают в Q1.

Цикл QMaster-thread последовательно проверяет счетчики Q1 и Q2 и, если какие-либо элементы находятся в q, он получает их и помещает их в Qmain.

Цикл Monitor-thread получает данные из внешних источников, упаковывает их и помещает в Q2.

Основной процесс приложения также запускает цикл, проверяющий счетчик Qmain, и, если он есть, получает элемент из Qmain на каждой итерации цикла и обрабатывает его дальше. Во время этой обработки он иногда помещает элемент в Q1 для последующей обработки (когда он по очереди получает от Qmain).

Эта проблема:
Я реализовал все как описано выше, и он работает в течение случайного (короткого) времени, а затем зависает. Мне удалось определить причину сбоя в увеличении / уменьшении счетчика fifo-q (это может произойти в любом из них).

Что я пробовал:
Используя три мьютекса: QMAIN_LOCK, Q1_LOCK и Q2_LOCK, которые я блокирую всякий раз, когда любая операция get / put выполняется на соответствующем fifo-q. Результат: приложение не запускается, просто зависает.

Основной процесс должен продолжаться все время, не должен блокироваться при «чтении» (сбой именованных каналов, сбой сокета пары).

Любой совет?
Я думаю, что неправильно внедряю мьютекс, как это должно быть сделано?
(Любые комментарии по улучшению вышеуказанного дизайна также приветствуются)

[edit] ниже приведены процессы и шаблон fifo-q:
Где и как в этом месте разместить мьютекс, чтобы избежать проблем, описанных выше?

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

Ответы на вопрос(6)

Ваш ответ на вопрос