2009-06-09 3 views
1

У меня есть вопрос о ситуации с потоком.Вопрос о синхронизации потоков

Предположим, у меня есть 3 темы: производитель, помощник и потребитель. поток производителя находится в запущенном состоянии (и другие два находятся в состоянии ожидания), и когда его выполнение вызывает вызовы, но проблема должна вызвать только вспомогательный поток, а не потребитель, то как он может убедиться, что после его выпуска ресурсов для получения только хелперной нити, а затем потребительской нитью.

заранее спасибо

+0

, обратите внимание, что в некоторых условиях несколько потоков могут находиться в рабочем состоянии (то есть многопроцессорная система и данные в процессе). – Adriaan

ответ

1

Вы могли бы, например, два мьютексы (или что вы используете): один для производителя и помощника, и другие для производителя и потребителя

Producer: 
    //lock helper 
    while true 
    { 
    //lock consumer 
    //do stuff 
    //release and invoke helper 
    //wait for helper to release 
    //lock helper again 
    //unlock consumer 
    //wait consumer 
    } 

Остальных просто блокировать и разблокировать нормально.

Еще один возможный подход (возможно, лучше) - использование мьютекса для производителя/помощника и другого помощника/потребителя; или, возможно, распределите эту задачу вспомогательного потока между двумя другими потоками. Не могли бы вы дать более подробную информацию?

+0

Измените 'mutex' как 'событие' или 'сигнал', и это хорошее предложение. Ожидание семафора, которое должно быть сигнализировано, является типичным способом установки состояний ожидания между потоками. Это не обеспечивает безопасность потоков общих данных, но это другая проблема. – Kieveli

1

Вспомогательная нить действительно является самой потребительской/самой производительной нитью. Напишите код для помощника, как и для любого другого потребителя, чтобы взять результат производителя. После этого напишите код для помощника, как и любой другой производитель, и подключите его к своей потребительской теме.

2

Или вы считали, что иногда отдельные темы - это скорее проблема, чем решение?

Если вы действительно хотите, чтобы операции в одном потоке были строго сериализованы с операциями в другом потоке, возможно, более простое решение - отбросить второй поток и структурировать код, чтобы первый поток выполнял операции в порядке желательно.

Это может быть не всегда возможно, но это то, что нужно помнить.

+0

+1 потому что вопрос, кажется, нуждается в вещах, которые нужно делать в последовательном, а не в параллельном режиме; в этом случае потоки просто переполнены, молоток ищет гвоздь. – mmr

+0

Хорошая проницательность - проблема в том, что процедурный программист впервые делает многопоточность и все еще делает свое программное обеспечение предназначенным для запуска в серийном режиме, но в нескольких потоках. Интересно. – Kieveli

1

Возможно, вы сможете использовать очереди, чтобы помочь вам с блокировками вокруг них. Производитель работает над чем-то, производит его и помещает в вспомогательную очередь. Помощник берет его, делает с ним что-то, а затем помещает его в очередь потребителей. Потребитель берет его, потребляет его и продолжает.

Что-то вроде этого:

Queue<MyDataType> helperQ, consumerQ; 
object hqLock = new object(); 
object cqLock = new object(); 

// producer thread 
private void ProducerThreadFunc() 
{ 
    while(true) 
    { 
     MyDataType data = ProduceNewData(); 
     lock(hqLock) 
     { 
      helperQ.Enqueue(data); 
     } 
    } 
} 

// helper thread 
private void HelperThreadFunc() 
{ 
    while(true) 
    {   
     MyDataType data; 
     lock(hqLock) 
     { 
      data = helperQ.Dequeue(); 
     } 

     data = HelpData(data); 
     lock(cqLock) 
     { 
      consumerQ.Enqueue(data); 
     } 
    } 
} 

// consumer thread 
private void ConsumerThreadFunc() 
{ 
    while(true) 
    {   
     MyDataType data; 
     lock(cqLock) 
     { 
      data = consumerQ.Dequeue(); 
     }    
     Consume(data);    
    } 
} 

ПРИМЕЧАНИЕ: Вам нужно будет добавить больше логики в этом примере, чтобы убедиться, годны к употреблению. Не ожидайте, что он будет работать как есть. В основном, используйте сигналы для одного потока, чтобы другие знали, что данные доступны в его очереди (или, как наихудший опрос, размер очереди, чтобы убедиться, что он больше 0, если он равен 0, затем спящий - но сигналы более чистые и более эффективные).

Этот подход позволит обрабатывать данные с разной скоростью (что может привести к проблемам с памятью).

Смежные вопросы