2013-04-19 14 views
5

मेरे पास एक ऐसा प्रोग्राम है जिसमें मैं एक बहु-निर्माता, बहु-उपभोक्ता सेटिंग को लागू करने की कोशिश कर रहा हूं। मेरे पास कोड है जो अच्छी तरह से काम करता है जब मेरे पास एक उपभोक्ता और एकाधिक उत्पादक हैं, लेकिन कई उपभोक्ता धागे पेश करना कुछ अजीब मुद्दों को उठाना प्रतीत होता है।एकाधिक उत्पादक एकाधिक उपभोक्ता थ्रेड इश्यू

यहाँ मैं अभी है:

#include <stdio.h> 
#include <pthread.h> 
#include <unistd.h> 
#include <stdlib.h> 

#define MAX 10 

typedef struct travs { 
    int id; 
    int numBags; 
    int arrTime; 
    struct travs *next; 
} travs; 


travs *queue; 
//travs *servicing[MAX]; 

int produced; // The total # of produced in the queue 

pthread_mutex_t queue_lock; 
//pthread_mutex_t staff_lock; 
pthread_cond_t ct, cs; 

int CheckIn(){ 
    sleep(1); 
    if(produced != 0) return 1; 
    else return 0; 
} 



void *producerThread(void *args){ 
    travs *traveler = (travs *)args; 
    // Acquire the mutex 
    pthread_mutex_lock(&queue_lock); 
    produced++; 
// pthread_cond_signal(&cs); 
    pthread_cond_wait(&ct, &queue_lock); 
    printf("Producer %d is now checked in at time %d.\n", queue->id, (1+queue- >arrTime)); 
    queue = queue->next; 
    pthread_mutex_unlock(&queue_lock); 

    return; 
}  

int Producer(int id, int numBags, int arrTime){ 

    int ret; 
    pthread_t ttid; 
    travs *traveler = malloc(sizeof(travs)); 
    traveler->id = id; 
    traveler->numBags = numBags; 
    traveler->arrTime = arrTime; 
    sleep(arrTime); 
    pthread_mutex_lock(&queue_lock); 
    if(queue != NULL) { 
     travs *check_in = malloc(sizeof(travs)); 
     check_in = queue; 
     while(check_in->next != NULL){ 
      check_in = check_in->next; 
     } 
     check_in->next = traveler; 
    } 
    else { queue = traveler; } 
    pthread_mutex_unlock(&queue_lock); 
    // Create a new traveler thread 
    ret = pthread_create(&ttid, NULL, producerThread, (void *)traveler); 

    // Check if thread creation was successful 
    if(ret == 0) { 
     printf("Producer %d has entered the check-in line at time %d; s/he is at  position %d and has %d bags.\n", id, arrTime, produced, numBags); 
     pthread_cond_signal(&cs); 
     return 0; 
    } 
    else return -1; 

} 


void *consumerThread(void *arg){ 

    int i = 0; // travelers serviced 
    char *name = (char *)arg; 
    while(1) { // run iteratively 

     // If 20 producers have been served, the consumer's work is done. 
     if(i == 20) { 
      printf("Consumer %s's service has completed!\n", name); 
       pthread_exit(NULL); 
      } 
     // Sleep for 10s if 5 travelers have been checked in 
     if (((i+1) % 5) == 0) { 
       // Wake up sleeping travelers 
       printf("Consumer %s is taking a break.\n", name); 
       sleep(2); 
       printf("Consumer %s's break is over.\n", name); 
     } 

     if(CheckIn()) { 
      pthread_mutex_lock(&queue_lock); 
      int j = 1; 
        pthread_cond_wait(&cs, &queue_lock); 
        printf("Producer %d presents ticket to consumer  %s.\n", queue->id, name); 
        printf("Consumer %s gives boarding pass to producer  %d.\n", name, queue->id); 
        while(j <= queue->numBags){ 
         printf("Consumer %s checks in bag %d for  producer %d; baggage tag is _X_.\n", name, j, queue->id); 
         j++; 
       } 
      // Signal producer being serviced that their check in is complete. 
      i++; 
      pthread_mutex_unlock(&queue_lock); 
      produced--; 
      pthread_cond_signal(&ct); 
     } 
    sleep(3); 
    } 
} 

int Consumer(char *Name) { 

    sleep(5); 
    int ret; 
    pthread_t stid; 
    // Create a staff thread 

    ret = pthread_create(&stid, NULL, consumerThread, (void *)Name); 
    // Acquire the lock 
    if(ret == 0) { 
     printf("Producer %s's service has begun!\n", Name); 
     return 0; 
    } 
    else return -1; 
} 

int main() { 
    int ret = 0; 
    char *staff_name = malloc(sizeof(char)); 
    int staff_check = 0; 
    int trav_check = 0; 
    int id; 
    int bagnum; 
    int travtime; 
    FILE *consumer_fp; 
    FILE *producer_fp; 
    queue = malloc(sizeof(travs)); 
    queue = NULL; 
    /*while(ret < 10){ 
     servicing[ret] = malloc(sizeof(travs)); 
     servicing[ret] = NULL; 
    }*/ 

    // Initilize mutexes 
    pthread_mutex_init(&queue_lock, NULL); 
    //pthread_mutex_init(&staff_lock, NULL); 

    // Initialize condition variables 
    pthread_cond_init(&ct, NULL); 
    pthread_cond_init(&cs, NULL); 

    // Open the file so we can start reading from it 

    consumer_fp = fopen("staff.txt", "r"); 
    producer_fp = fopen("travelers.txt", "r"); 

    staff_check = fscanf(consumer_fp, "%s", staff_name); 
    trav_check = fscanf(producer_fp, "%d %d %d", &id, &bagnum, &travtime); 
    while(1){ 

     K: 
     while(staff_check == 1) { 
      Consumer(staff_name); 
      staff_check = fscanf(consumer_fp, "%s", staff_name); 
      goto L; 
     } 
     L: 
     while(trav_check == 3) { 
      Producer(id, bagnum, travtime); 
      trav_check = fscanf(producer_fp, "%d %d %d", &id, &bagnum,  &travtime); 
      goto K; 
     } 

    pthread_exit(NULL); 
    } 

} 

इस सेटिंग में, हर निर्माता धागा लौटने से पहले केवल थोड़े समय के लिए रहता है, और वैश्विक कतार में एक नया तत्व जोड़ के अलावा कोई वास्तविक गणना में ही करता है और कुछ उपयुक्त समय आउटपुट लाइनें।

हालांकि, जब मैं कई उत्पादकों को पेश करता हूं, केवल अंतिम निर्माता धागा कुछ भी करता है।

मैं क्या समझ में आता है से, मैं निम्नलिखित की जरूरत है:

i) इंतज़ार कर करने के लिए चेक-इन किया और निर्माता रहे हैं जो वर्तमान में किया जा रहा चेक-इन किया उत्पादकों के लिए अलग कतार (travs के रूप में बाहर टिप्पणी की * सर्विसिंग [मैक्स] उपरोक्त)

ii) उपभोक्ताओं के लिए एक अलग म्यूटेक्स।

हालांकि, मुझे यकीन नहीं है कि इसे कैसे कार्यान्वित किया जाए। यह विचार मेरे मन में था:

  1. चेकइन() एक निर्माता धागा और प्रतिलिपि * कतार में * सर्विसिंग [i] (उपभोक्ता सूत्र में)।

  2. सेट कतार = कतार-> अगला (निर्माता थ्रेड में)।

लेकिन, मैं कैसे सुनिश्चित कर सकते हैं जब मैं पर कॉपी * कतार यह पहले से ही एक कदम उन्नत नहीं होगा कि कि है? क्या मैं वर्तमान में रखे गए थ्रेड से अलग लॉक के साथ प्रतीक्षा थ्रेड सिग्नल कर सकता हूं? और, सबसे महत्वपूर्ण बात यह है कि मेरे पास अलग-अलग उपभोक्ता धागे अलग-अलग यात्री धागे को कैसे संसाधित करेंगे?

किसी भी सहायता की सराहना की जाएगी!

travs *traveler = malloc(sizeof(travs)); 
traveler = (travs *)args; 

मैं के बारे में "क्या मेमोरी लीक के बारे में इतना बुरा है?" विस्तार में जाने के लिए नहीं जा रहा हूँ:

+0

'travs * traveler = malloc (sizeof (travs)); यात्री = (travs *) तर्क; 'एक स्मृति रिसाव है ... – Sebivor

+0

आह, पकड़ के लिए धन्यवाद। मैं वहां एक मुफ्त लाइन जोड़ दूंगा। – user991710

उत्तर

3

एक कतार का उपयोग करें।

दो कार्य लिखें, एक मौजूदा आइटम को कतार में जोड़ने के लिए और एक कतार से किसी आइटम को निकालने के लिए। इन कार्यों में किसी भी लॉकिंग का उपयोग न करें। उन्हें एक थ्रेडेड एप्लिकेशन में टेस्ट करें।

फिर दो दो रैपर को ऐसे दो ऐड-एंड हटाने-कार्यों में लिखें। उन रैपरों को तर्क के रूप में एक addtionally mutex लेना चाहिए। एड-या हटाने-फ़ंक्शन को कॉल करने से पहले इस म्यूटेक्स को रैपर में लॉक करें और बाद में म्यूटेक्स को अनलॉक करें।

निर्माता थ्रेड फ़ंक्शन को एक नया आइटम बनाने और एड-आइटम-रैपर को कॉल करने के लिए लिखें। निकालें-आइटम-रैपर को कॉल करने और हटाए गए आइटम को नष्ट करने वाले उपभोक्ता थ्रेड फ़ंक्शन को लिखें।

main() फ़ंक्शन घोषित करने और म्यूटेक्स को प्रारंभ करने के लिए सेट करें, फिर pthread_create() का उपयोग करके उत्पादकों और उपभोक्ताओं के विभिन्न उदाहरण बनाने के लिए जाएं। Mutex को धागे कार्यों के लिए तर्क के रूप में पास करें।

+0

चरणबद्ध उत्तर के लिए धन्यवाद। मैं छोटे कार्यक्रमों से शुरू होने वाले पूरे कार्यक्रम को फिर से लिखता हूं और यह कई उत्पादकों और एक उपभोक्ता के लिए सही तरीके से काम कर रहा है। मुझे अभी भी कई उपभोक्ताओं के साथ समस्याएं हैं जिन्हें मैं निदान नहीं कर सकता, लेकिन मैं इसे एक अलग प्रश्न के रूप में पोस्ट कर सकता हूं। किसी भी तरह से, क्योंकि इससे मुझे अर्ध-कामकाजी समाधान मिल गया, मैं इसे एक उत्तर के रूप में स्वीकार करूंगा। धन्यवाद। – user991710

4

जैसा कि मैंने उल्लेख किया है, यह एक स्मृति रिसाव है। अगर आप वह जवाब चाहते हैं, तो Google से यह प्रश्न पूछें। आप शायद मतलब: travs *traveler = args;


if(queue != NULL) { 
    travs *check_in = malloc(sizeof(travs)); 
    check_in = queue; 
    while(check_in->next != NULL){ 
     check_in = check_in->next; 
    } 
    check_in->next = traveler; 
} 
else { queue = traveler; } 

मेमोरी रिसाव एक तरफ रख दिया, क्यों कतार म्युटेक्स, अन्य कार्यों में पहले से सुरक्षित है, जबकि वहाँ कोई म्युटेक्स इस कोड में सभी पर की रखवाली है? ऐसा लगता है कि आप म्यूटेक्स के बिंदु को याद कर चुके हैं। आपका कोड रेस, यहां।

शायद pthread_rwlock_t एस इस तरह के कोड के लिए अधिक उपयुक्त होगा।

+0

कोड के उस खंड में रिसाव और म्यूटेक्स की कमी को नोट करने के लिए धन्यवाद, लेकिन दुर्भाग्य से यह अभी भी कई उपभोक्ताओं के डिजाइन के प्रश्न का उत्तर नहीं देता है! – user991710

संबंधित मुद्दे