2016-01-31 4 views
9

Я писал программу, которая запускает два процесса.Два типа сообщений в очереди сообщений

Первый процесс, «клиент» отправляет два типа сообщений.

Первый тип увеличивает общий ресурс (int). Второй тип устанавливает ресурс в 0.

После 10 сообщений клиент должен отправить сообщение со специальным типом, который заставляет потоки, прослушивающие две очереди, остановиться. Таким образом, клиент отправляет два сообщения (по одному для каждой очереди) со специальным значением в поле типа для прекращения потоков.

Второй процесс - это «сервер».

Сервер имеет три темы:

первый прослушиваемых на «увеличение» очереди. Он должен обрабатывать запрос увеличения до сообщения о завершении. Я писал:

do{ 
msgrcv(id_i,&msg,dimensione,INCREMENTA,0); 
pthread_mutex_lock(&mutex); 
printf("THREAD 1: Il contatore vale:%d\n",*contatore); 
incremento = msg.contenuto; 
printf("THREAD 1: Incremento di : %d\n",incremento); 
    *contatore+=incremento; 
printf("THREAD 1: Il contatore vale:%d\n",*contatore); 
pthread_mutex_unlock(&mutex); 
msgrcv(id_i,&msg,dimensione,TERMINA,IPC_NOWAIT); //IPC_NOWAIT or the thread will 
freeze after the first message 
} 
while(msg.tipo!=TERMINA); 

Второй должен обрабатывать запросы «установить до 0» до сообщения о завершении.

do{msgrcv(id_a,&msg,dimensione,AZZERA,0); 
pthread_mutex_lock(&mutex); 
printf("THREAD 2: IL CONTATORE VALE:%d\n",*contatore); 
*contatore=0; 
printf("Thread 2: Contatore azzerato. Ora vale : %d\n",*contatore); 
pthread_mutex_unlock(&mutex); 
msgrcv(id_a,&msg,dimensione,TERMINA,IPC_NOWAIT);//IPC_NOWAIT or the thread will 
freeze after the first message 
} 
while(msg.tipo!=TERMINA); 

Третий поток увеличивает ценность ресурса с использованием мьютекса для взаимного исключения.

Проблема в том, что thread1 и thread2 серверного процесса не заканчиваются там, где они должны. Фактически, они застряли в первом msgrcv() после всех сообщений об увеличении/set0. Таким образом, проблема в том, что двум потокам не удается прослушать сообщение о завершении.

Я попытался установить IPC_NOWAIT также для первого msgrcv, но не работает

ответ

8

Вы, опираясь на условия гонки, один, что вы почти никогда не выиграет.

Давайте посмотрим на первый блок:

do { 
    // Note the msg type:   vvvvvvvvvv 
    msgrcv(id_i, &msg, dimensione, INCREMENTA, 0); 

    // ... 

    // Note the msg type:   vvvvvvv 
    msgrcv(id_i, &msg, dimensione, TERMINA, IPC_NOWAIT); 
} 
while(msg.tipo != TERMINA); 

Это второй вызов «msgrcv» в цикле ваша попытка искать типа терминатор сообщения, прежде чем вы петлю обратно к верхней и блока, ожидание другой INCREMENTA сообщение.

Рассмотрим следующую цепочку событий:

Sender    Receiver 
    ---------------  ----------------- 
1      Call msgrcv with INCREMENTA. Block indefinitely 
2 Send 'INCREMENTA' 
3      msgrcv returns. Begin processing increment msg. 
4      Processing finshed. 
5      Call msgrcv with TERMINA. 
6      No TERMINA message found (queue empty), returns immediately. 
7      Go to top of loop. 
8      Call msgrcv with INCREMENTA. Block indefinitely 
9 Send 'TERMINA'  
10      Nothing happens because we're waiting for 'INCREMENTA'. 

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

Вместо этого, почему бы не использовать msgrcv для получения сообщений какого-либо типа, а затем после прочтения сообщения из очереди выяснить, какой тип сообщения вы получили и как его обрабатывать. Если вы передадите 0 для параметра «msgtyp» в msgrcv, он предоставит вам все сообщения, а затем вы сможете обработать его, как вам угодно.

while(true) { 

     // Get any msg type:   vv 
     msgrcv(id_i, &msg, dimensione, 0, 0); 

     if (msg.tipo == TERMINA) { 
      break; 
     } 
     else { 
      // ... 
     } 
    } 
+0

Got it. Ответ принят. – EagleOne

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