2012-05-23 12 views
6

मैंने पाइथन में पहले मल्टीथ्रेडिंग लाइब्रेरी का उपयोग किया है, लेकिन यह पहली बार है जब मैं सी में थ्रेडिंग की कोशिश कर रहा हूं। मैं श्रमिकों का पूल बनाना चाहता हूं। बदले में, इन श्रमिकों चाहिए करने के लिए धक्का या queue.Following कोड काफी वहाँ अभी तक नहीं है से पॉप, लेकिन मैं अब तक क्या किया है है:थ्रेड सुरक्षित कतारों को कार्यान्वित करने के लिए कैसे करें

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#define NUMTHREADS 20 /* number of threads to create */ 

typedef struct node node; 
typedef struct queue queue; 

struct node { 
    char *name; 
    node *next; 
}; 

struct queue { 
    node *head; 
    node *tail; 
}; 

/* pop: remove and return first name from a queue */ 
char *pop(queue *q) 
{ 
    if (q->head == NULL) 
     return NULL; 
    char *name = q->head->name; 
    node *tmp = q->head; 
    q->head = q->head->next; 
    free(tmp); 
    return name; 
} 

/* push: add name to the end of the queue */ 
int push(queue *q, char *name) 
{ 
    node *new = malloc(sizeof(node)); 
    if (new == NULL) 
     return -1; 
    new->name = name; 
    new->next = NULL; 
    if (q->tail != NULL) 
     q->tail->next = new; 

    q->tail = new; 
    if (q->head == NULL) /* first value */ 
     q->head = new; 
    return 0; 
} 

/* printname: get a name from the queue, and print it. */ 
void *printname(void *sharedQ) 
{ 
    queue *q = (queue *) sharedQ; 
    char *name = pop(q); 
    if (name == NULL) 
     pthread_exit(NULL); 
    printf("%s\n",name); 
    pthread_exit(NULL); 
} 

int main() 
{ 
    size_t i; 
    int rc; 
    pthread_t threads[NUMTHREADS]; 
    char *names[] = { 
     "yasar", 
     "arabaci", 
     "osman", 
     "ahmet", 
     "mehmet", 
     "zeliha" 
    }; 

    queue *q = malloc(sizeof(queue)); 
    q->head = NULL; 
    q->tail = NULL; 

    /* number of elements in the array */ 
    size_t numelems = sizeof(names)/sizeof(char *); 

    for (i = 0; i < numelems; i++) /* push each name */ 
     push(q, names[i]); 

    for (i = 0; i < NUMTHREADS; i++) { /* fire up threads */ 
     rc = pthread_create(&threads[i], NULL, printname, 
       (void *)q); 
     if (rc) { 
      printf("Error, return code from pthread is %d\n", rc); 
      exit(-1); 
     } 
    } 

    pthread_exit(NULL); 
} 

मैं कोड से ऊपर की कोशिश की है, और यह हमेशा एक नाम ठीक वैसे ही मुद्रित एक बार। यह किसी भी नाम को छोड़ नहीं पाया, या दो बार मुद्रित नाम। दूसरी तरफ, मुझे यकीन नहीं है कि इस कतार कार्यान्वयन को कैसे सुरक्षित किया गया है। तो मेरा सवाल है, क्या यह एक थ्रेडसेफ कतार है? यदि नहीं, तो क्यों नहीं? और इसे धागा सुरक्षित कैसे बनाया जाए?

+0

structs को typedefs की आवश्यकता नहीं है; उनके पास पहले से ही एक प्रकार है। –

उत्तर

5

कोड धागा सुरक्षित नहीं है।

पुश और पॉप फ़ंक्शन थ्रेड सुरक्षित नहीं हैं। कोड में, पुश केवल एक धागे द्वारा निष्पादित किया जा रहा है, इसलिए इससे कोई फर्क नहीं पड़ता है, लेकिन पॉप को कई धागे द्वारा निष्पादित किया जा रहा है।

1. char *name = q->head->name; 
2. node *tmp = q->head; 
3. q->head = q->head->next; 
4. free(tmp); 

कल्पना कीजिए धागा एक और सहित लाइन 2. थ्रेड बी करने के लिए निष्पादित करता है तो अप करने के लिए निष्पादित करता है और सहित लाइन 4. थ्रेड एक निष्पादन शुरू। यह पता चलता है कि q-> सिर पहले ही मुक्त हो चुका है() ed।

अब, यह अब तक तर्कसंगत मुद्दों पर चर्चा करता है।

हालांकि, विचार करने के लिए शारीरिक मुद्दे हैं।

कल्पना कीजिए कि हमारे पास लॉकिंग तंत्र था जिससे धागे उनके व्यवहार को सिंक्रनाइज़ कर सकें, जैसे कि एक समय में केवल एक थ्रेड लाइन 1 से 4 में कोड निष्पादित कर सकता है, उदा। एक म्यूटेक्स, जो एक ऑब्जेक्ट है, केवल एक थ्रेड एक समय में 'होल्ड' कर सकता है, और होल्डिंग थ्रेड रिलीज़ होने तक म्यूटेक्स थ्रेड को अवरुद्ध करने का प्रयास करता है।

0. get mutex 
1. char *name = q->head->name; 
2. node *tmp = q->head; 
3. q->head = q->head->next; 
4. free(tmp); 
5. release mutex 

हम अभी भी, एक समस्या है कि में किसी भी सीपीयू कोर द्वारा किया जाता राईट (थ्रेड नहीं) दिखाई तुरंत ही उस कोर पर धागे के लिए कर रहे हैं; अन्य कोरों पर धागे नहीं।

निष्पादन को सिंक्रनाइज़ करने के लिए पर्याप्त नहीं है; साथ ही, हमें यह भी सुनिश्चित करना होगा कि कोर द्वारा किए गए लेखन अन्य कोरों के लिए दृश्यमान हो जाएं।

(अन) सौभाग्य से, सभी आधुनिक सिंक्रनाइज़ेशन विधियां भी इस लेखन को फ्लशिंग करती हैं (उदाहरण के लिए जब आप एक म्यूटेक्स प्राप्त करते हैं, तो आप स्मृति को सभी लिखते हैं)। मैं दुर्भाग्य से कहता हूं, क्योंकि आप नहीं करते- इस व्यवहार की आवश्यकता है और यह प्रदर्शन के लिए हानिकारक है।

3

यह थ्रेड-सुरक्षित नहीं है क्योंकि एकाधिक धागे एक ही समय में लिंक्ड सूची में पॉइंटर्स को संशोधित कर सकते हैं, संभावित रूप से इसे दूषित कर सकते हैं। Multiple-writer thread-safe queue in C

वहाँ आप देख सकते हैं कि कतार धागा सुरक्षित बनाने के लिए:

यहाँ आप एक बहुत समान प्रश्न के लिए एक जवाब है।

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

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