2014-10-06 7 views
8

निम्नलिखित प्रोग्राम है जो pthreads का उपयोग करता है।एक बहुप्रचारित प्रोग्राम में अप्रत्याशित आउटपुट

#include <pthread.h> // posix threads 
#include <stdio.h> 
#include <stdlib.h> 

/* to compile use -lpthread */ 

void * sample_thread(void *); 

#define MAX 10 

int main() 
{ 
    pthread_t tid; 
    pthread_attr_t attr; 
    int k; 

    pthread_attr_init(&attr); // set default attributes 
    pthread_create(&tid, &attr, sample_thread, NULL); // create new thread 
    // sample_thread will run as the new thread 

    for(k=0; k<MAX; k++) { 
    printf("Hi I'am %s %d \n",__func__,k); 
    } 


    //this would kill all the threads, 
} 

void * sample_thread(void * p) 
{ 
    int k; 
    for(k=0; k<MAX; k++) { 
    printf("Hi I'am %s %d \n",__func__,k); 
    } 

} 

हर बार जब मैं इस कार्यक्रम मैं मुख्य थ्रेड से निष्पादन संख्याओं के विभिन्न संख्या और बच्चे धागा (क्योंकि बच्चे से पहले मुख्य थ्रेड हो सकता है निकास) प्राप्त करने के लिए उम्मीद कर रहा हूँ चलाते हैं। मुझे कभी-कभी यह उम्मीद आउटपुट मिल रहा है। लेकिन मुझे निम्नानुसार एक आउटपुट मिला, जिसे मैं समझने में असमर्थ हूं।

Hi I'am main 0 
Hi I'am main 1 
Hi I'am main 2 
Hi I'am main 3 
Hi I'am main 4 
Hi I'am main 5 
Hi I'am main 6 
Hi I'am main 7 
Hi I'am main 8 
Hi I'am main 9 
Hi I'am sample_thread 0 
Hi I'am sample_thread 0 
Hi I'am sample_thread 1 
Hi I'am sample_thread 2 
Hi I'am sample_thread 3 
Hi I'am sample_thread 4 
Hi I'am sample_thread 4 
Hi I'am sample_thread 5 

नमूना धागा 0 और 4 प्रिंट दो बार क्यों किया?

+1

क्या आप हमें बता सकते हैं कि आप किस ओएस का उपयोग कर रहे हैं? आपके प्रोग्राम में कुछ भी गलत नहीं लगता है और मुझे संदेह है कि यह कार्यान्वयन में एक बग हो सकता है (पीओएसआईक्स द्वारा एसटीडीओ ऑपरेशंस के साथ सिंक्रनाइज़ करने के लिए 'निकास' की आवश्यकता है, लेकिन अगर ऐसा करने में असफल रहा, तो डेटा दौड़ हो सकती है (और यादृच्छिक भ्रष्टाचार) जब यह 'stdout'' के साथ एक और थ्रेड लेखन के साथ 'stdout' फ्लश करता है)। –

+0

यह पहले विकल्प के बारे में उबंटू 13.10 – DesirePRG

उत्तर

8

टिप्पणियों में @R .. द्वारा हाइलाइट किया गया है, यह ग्लिब के कार्यान्वयन में a bug प्रतीत होता है (माना जाता है कि आप लिनक्स का उपयोग कर रहे हैं - मैं इसे जीसीसी 4.9.1 के साथ संकलित लिनक्स 2.17 पर पुन: पेश कर सकता हूं) exit() सुनिश्चित नहीं करता है, स्ट्रीमों को फ़्लश करने और बंद करने के दौरान, जब कोई थ्रेड स्टडआउट का उपयोग करता है तो उसे एक थ्रेड द्वारा कॉल किया जाता है जब कोई दौड़ नहीं होती है।

flockfile पुस्तिका से निम्नलिखित स्पष्ट रूप से इंगित करता है कि व्यवहार मनाया सही नहीं है:

stdio कार्यों धागा सुरक्षित हैं। यह द्वारा प्रत्येक फ़ाइल ऑब्जेक्ट को लॉककाउंट को असाइन करने और (यदि लॉककाउंट nonzero है) एक स्वामित्व थ्रेड द्वारा प्राप्त किया जाता है। प्रत्येक लाइब्रेरी कॉल के लिए, ये फ़ंक्शन तब तक प्रतीक्षा करें जब तक कि FILE ऑब्जेक्ट को थ्रेड द्वारा लॉक नहीं किया जाता है, फिर इसे लॉक करें, अनुरोध किया गया I/O करें, और ऑब्जेक्ट फिर से अनलॉक करें।

इस के प्रकाश में, निम्नलिखित विकल्पों को इस विशेष मामले में वर्कअराउंड (जैसा कि बग रिपोर्ट के लिए कोई प्रतिक्रिया नहीं है) के रूप में माना जा सकता है।


दोनों धागे "साझा" stdout स्ट्रीम और मुझे लगता है कि, "अतिरिक्त" उत्पादन मुख्य थ्रेड के समय से पहले बाहर निकलने की वजह से छपा है।

printf बफर (sample_thread() में) आउटपुट और इससे पहले कि यह बफर को साफ़ कर सके (प्रिंटर में \n के कारण), मुख्य थ्रेड निकलता है। इसलिए प्रक्रिया समाप्त होने पर stdout बफर की फ्लश को मजबूर करना।

ठीक करने के लिए,

1) आप धागा बनाने से पहले main() में setbuf() कह सकते हैं:

setbuf(stdout, NULL); 

के लिए नहीं बफर stdout बिल्कुल।

या
2) दोनों धागे में pthread_exit() पर कॉल करें ताकि प्रक्रिया जारी रहे या तो थ्रेड मर जाए।

या
3) मुख्य धागे में pthread_join() पर कॉल करें ताकि मुख्य धागा sample_thread थ्रेड के पूरा होने की प्रतीक्षा कर सके।

इनमें से कोई भी इस मुद्दे से बच जाएगा।

+0

है। मुझे सेटबफ फ़ंक्शन कहां से कॉल करना चाहिए? दूसरे विकल्प के बारे में – DesirePRG

+1

केवल मुख्य कार्य में pthread_exit को कॉल नहीं कर रहा है? – DesirePRG

+1

1. बफर के पहले उपयोग को सेट करने से पहले 'setbuf()' रखें। यहां: 'stdout'' printf() 'द्वारा स्पष्ट रूप से उपयोग करें। 2. 'मुख्य()' में 'pthread_exit()' को कॉल करना पर्याप्त है। – alk

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