2016-01-31 37 views
9

Tôi đã viết một chương trình bắt đầu hai quy trình.Hai loại tin nhắn trong một hàng đợi tin nhắn

Quy trình đầu tiên, "khách hàng" gửi hai loại thư.

Loại đầu tiên tăng tài nguyên được chia sẻ (int). Loại thứ hai đặt tài nguyên thành 0.

Sau 10 thư, khách hàng phải gửi thư có loại đặc biệt buộc các luồng nghe trên hai hàng đợi dừng lại. Vì vậy, khách hàng sẽ gửi hai tin nhắn (một cho mỗi hàng đợi) với một giá trị đặc biệt trong trường loại để chấm dứt các chủ đề.

Quy trình thứ hai là "máy chủ".

Máy chủ có ba luồng:

đầu tiên đang nghe trên hàng đợi "tăng". Nó phải xử lý yêu cầu tăng cho đến khi thông báo kết thúc. Vì vậy, tôi đã viết:

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); 

Thứ hai phải xử lý yêu cầu "được đặt thành 0" cho đến khi thông báo chấm dứt.

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); 

Chủ đề thứ ba tăng giá trị của tài nguyên bằng cách sử dụng mutex để loại trừ lẫn nhau.

Vấn đề là thread1 và thread2 của quá trình máy chủ không chấm dứt nơi họ nên. Trong thực tế, họ bị mắc kẹt trên msgrcv đầu tiên() sau tất cả các thông báo tăng/set0. Vì vậy, vấn đề là hai chủ đề không thể quản lý để nghe thông báo chấm dứt.

Tôi cố gắng để thiết lập IPC_NOWAIT cũng cho msgrcv đầu tiên nhưng đã không làm việc

Trả lời

8

Bạn đang dựa vào một điều kiện chủng tộc, một trong những bạn sẽ hầu như không bao giờ giành chiến thắng.

Chúng ta hãy nhìn vào khối đầu tiên:

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); 

Đó thứ hai gọi 'msgrcv' trong vòng lặp là nỗ lực của bạn để tìm kiếm một loại thông điệp terminator, trước khi bạn lặp lại để đầu và block, đang đợi một tin nhắn khác INCREMENTA.

Hãy xem xét các chuỗi sự kiện sau:

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'. 

Bạn không thể cố gắng truy vấn hàng đợi thông điệp trong mô hình này. Nếu các sự kiện 8 và 9 đã được đảo ngược, logic của bạn sẽ xảy ra để làm việc - nhưng đó là một điều kiện đua, và một trong đó bạn có khả năng bị mất thường xuyên. Thay vào đó, tại sao không sử dụng msgrcv để nhận bất kỳ loại thư nào, sau đó sau khi đọc thư từ hàng đợi, hãy tìm ra loại thư bạn đã nhận và xử lý thư từ đó. Nếu bạn vượt qua 0 cho thông số 'msgtyp' tới msgrcv, thông số sẽ cung cấp cho bạn tất cả thư và sau đó bạn có thể xử lý thông báo theo cách bạn muốn.

while(true) { 

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

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

OK. Đã chấp nhận câu trả lời. – EagleOne

Các vấn đề liên quan