2012-04-16 30 views
6

के रूप में काम नहीं करता मैंने एक कार्यक्रम लिखा था और यह काम नहीं करता है क्योंकि मैं इसकी उम्मीद करता हूं। मेरे पास दो धागे हैं: thread ट्रिगर्स func और anotherThreadanotherFunc ट्रिगर्स। मैं क्या करना चाहता था जब cont10func, anotherThreadpthread_cond_wait और pthread_cond_signal का उपयोग करके ट्रिगर करने के लिए मूल्य 10 तक पहुंचता है। अगर मैं sleep(1) लाइन को असम्बद्ध करता हूं तो अजीब चीज सब ठीक काम करती है। मैं धागे के लिए नया हूं और मैं ट्यूटोरियल here का पालन कर रहा था और यदि मैं उनके उदाहरण में sleep लाइन पर टिप्पणी करता हूं तो यह भी टूट जाता है।पॉज़िक्स सी थ्रेड्स। उदाहरण के लिए pthread_cond_t। अपेक्षित

मेरा सवाल यह है कि मैं बिना किसी sleep() कॉल के बिना यह काम कैसे कर सकता हूं? और क्या होता है यदि मेरे कोड में funcanotherFunc के बाद pthread_mutex_lock तक पहुंचता है? मैं इन चीजों को कैसे नियंत्रित कर सकता हूं? यह मेरा कोड है:

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

pthread_mutex_t myMutex; 
pthread_cond_t cond; 
pthread_attr_t attr; 

int cont; 

void *func(void*) 
{ 
    printf("func\n"); 

    for(int i = 0; i < 20; i++) 
    { 
     pthread_mutex_lock(&myMutex); 

     cont++; 
     printf("%d\n", cont); 
     if(cont == 10) 
     { 
      printf("signal:\n"); 
      pthread_cond_signal(&cond); 
//   sleep(1); 
     } 
     pthread_mutex_unlock(&myMutex); 
    } 
    printf("Done func\n"); 

    pthread_exit(NULL); 
} 

void *anotherFunc(void*) 
{ 
    printf("anotherFunc\n"); 
    pthread_mutex_lock(&myMutex); 
    printf("waiting...\n"); 

    pthread_cond_wait(&cond, &myMutex); 
    cont += 10; 
    printf("slot\n"); 

    pthread_mutex_unlock(&myMutex); 
    printf("mutex unlocked anotherFunc\n"); 
    printf("Done anotherFunc\n"); 

    pthread_exit(NULL); 
} 

int main(int argc, char *argv[]) 
{ 
    pthread_t thread; 
    pthread_t anotherThread; 

    pthread_attr_init(&attr); 
    pthread_mutex_init(&myMutex, NULL); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
    pthread_cond_init(&cond, NULL); 

    pthread_create(&anotherThread, &attr, anotherFunc, NULL); 
    pthread_create(&thread, &attr, func, NULL); 

    pthread_join(thread, NULL); 
    pthread_join(anotherThread, NULL); 

    printf("Done MAIN()"); 

    pthread_mutex_destroy(&myMutex); 
    pthread_cond_destroy(&cond); 
    pthread_attr_destroy(&attr); 


    pthread_exit(NULL); 
    return 0; 
} 

लंबे पद के लिए क्षमा करें, लेकिन मैं धागे के लिए नया हूँ और मैं जानने के लिए तैयार हूँ। क्या आप लिनक्स पर धागे और नेटवर्किंग पर कुछ अच्छे संदर्भ या पाठ्यक्रम/ट्यूटोरियल भी जानते हैं? मैं एक चैट क्लाइंट बनाना सीखना चाहता हूं और मैंने सुना है कि मुझे इसके लिए धागे और नेटवर्किंग जानना है। समस्या यह है कि अगर मैं सीखता हूं तो मुझे बहुत अच्छा पता नहीं है क्योंकि मुझे नहीं पता कि मुझे क्या पता होना है।

बहुत बहुत शुक्रिया :)

+0

अन्य टिप्पणियां। मैं 'pthread_attr_t' का उपयोग न करने के अलावा, आप कोड को सरल बनाने के लिए स्थिति और म्यूटेक्स के लिए स्थिर प्रारंभकर्ताओं का उपयोग कर सकते हैं। इसके अलावा, आपके थ्रेड फ़ंक्शन 'pthread_exit' को कॉल करने के बजाय' वापस लौट सकते हैं 'या 'वापसी 0;' कर सकते हैं। और आपका मुख्य धागा 'pthread_exit' को कॉल किए बिना मुख्य रूप से' वापस 0; 'कर सकता है। अन्य धागे उस बिंदु पर नहीं चल रहे हैं क्योंकि वे शामिल हुए थे। मुख्य बलों से एक प्रक्रिया से बाहर निकलें, लेकिन प्राथमिक थ्रेड में 'pthread_exit' एक प्रक्रिया से बाहर निकलने के लिए मजबूर नहीं होता है, जो अन्य थ्रेड चलने के लिए उपयोगी है। – Kaz

+0

इसके अलावा, स्थैतिक म्यूटेक्स और शर्तों को साफ करने की कोई आवश्यकता नहीं है। बस 'pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER; 'का उपयोग करें। परिस्थितियों के लिए जटिल प्रारंभिकरण की आवश्यकता होती है जहां आप असामान्य विशेषताओं को सेट करना चाहते हैं। जैसे एक प्रक्रिया-साझा मजबूत म्यूटेक्स बनाओ। – Kaz

उत्तर

9

आपका anotherThread बस पहले परीक्षण है कि क्या वांछित हालत (काउंटर तक पहुँचने दस) पहले से ही हुआ है बिना pthread_cond_wait कहता है। यह गलत तर्क है, जो खो गया जागरूकता समस्या: आवर्ती बग का नाम है जो गलत तरीके से लिखे गए बहुप्रचारित प्रोग्रामों को पीड़ित करता है।

हालत चर स्थिर हैं। यदि pthread_cond_signal या pthread_cond_broadcast ऐसी स्थिति पर कॉल किया जाता है जिस पर कोई थ्रेड वर्तमान में प्रतीक्षा नहीं कर रहा है, तो ऑपरेशन का कोई प्रभाव नहीं पड़ता है। यह याद नहीं है। तो आपके सिग्नलिंग थ्रेड के लिए 10 पर बहुत तेज़ी से गिनना संभव है, और अन्य धागे pthread_cond_wait कॉल तक पहुंचने से पहले, स्थिति परिवर्तनीय को संकेत दें।

आपको pthread_cond_wait के आसपास एक लूप की आवश्यकता है। स्थिति पहले से ही सही होने पर जांच की जानी चाहिए, ताकि थ्रेड पहले से हुआ एक जागने की प्रतीक्षा न करे। और यह एक पाश क्योंकि wakeups नकली हो सकता है किया जाना चाहिए: सिर्फ इसलिए कि धागा pthread_cond_wait के माध्यम से गिर जाता है मतलब नहीं है कि हालत वास्तव में सच है:

while (cont < 10) 
    pthread_cond_wait(&cond, &myMutex); 

इसके अलावा, वहाँ सिर्फ एक धागा विशेषता बनाने की आवश्यकता है एक धागा शामिल करने के लिए। जब आप सृजन विशेषता के लिए शून्य सूचक का उपयोग करते हैं तो यह डिफ़ॉल्ट स्थिति होती है। POSIX धागे तब तक जुड़ने योग्य होते हैं जब तक अलग-अलग डिज़ाइन नहीं किया जाता है, या pthread_detach के साथ अलग करने के लिए परिवर्तित किया जाता है।

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

+0

आपका दूसरा थ्रेड केवल पहले परीक्षण किए बिना pthread_cond_wait को कॉल करता है चाहे वांछित स्थिति (दस तक पहुंचने वाला काउंटर) पहले से ही हुआ है मैंने सोचा था कि स्थिति चर इस तरह काम करते हैं: जब निष्पादन pthread_cond_wait तक पहुंच जाता है, तो सिग्नल प्राप्त होने तक थ्रेड फ्रीज हो जाता है। मुझे मौसम का परीक्षण क्यों करना है वांछित स्थिति पहले से ही हो चुकी है क्योंकि यह हालत परिवर्तनीय कार्य है? मेरा मतलब है ... मुझे हालत चर की आवश्यकता क्यों है क्योंकि मैं जांचने के लिए सिर्फ एक लूप कर सकता हूं कि मेरी हालत कब पहुंच गई है और उदाहरण के लिए इसका ध्वज बनाएं। और जब वह ध्वज सत्य होता है, तो दूसरा थ्रेड निकलता है। –

+0

मैंने लूप में pthread_cond_wait को डालने की कोशिश की जैसा आपने कहा था लेकिन यह अभी भी काम नहीं करता है ... http://pastebin.com/tNB9wCMW मैं बहुत उलझन में हूं क्योंकि मुझे समझ में नहीं आता कि आप कैसे नियंत्रित कर सकते हैं धागे इतने निष्पादन pthread_cond_signal आपके उत्तरों के लिए धन्यवाद –

+0

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

2

मुझे नहीं पता कि आपकी वास्तविक समस्या क्या है (जब यह काम नहीं करता है तो क्या होता है?) ..

मुझे एक बड़ी समस्या दिखाई देती है, आप spurious wakeups को संभाल नहीं करते हैं।

init:

signaled = false; 

संकेत:

signaled = true; 
pthread_cond_signal(&cond); 

प्राप्त करते हैं:

while (!signaled) 
    pthread_cond_wait(&cond, &myMutex); 

आप एक बूलियन चर के साथ कुछ ऐसा है जो कि हालत वास्तव में सच का संकेत, उदाहरण के लिए की जरूरत है

+0

बड़ी समस्या * खो * जागरूकता है, जिसके लिए आपको 'pthread_cond_wait' के आस-पास' if' की आवश्यकता है। नकली wakeupup एक मामूली समस्या है जिसके लिए एक 'समय' होना आवश्यक है। यह असंभव है कि इस एक शॉट की स्थिति में केवल दो धागे के साथ एक नकली जागरूकता भी होगी। – Kaz

+0

yepp, मैंने आपका उत्कृष्ट जवाब देखा;) –

0

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

यह बस एक अलग विकल्प है।

1

आप जो चाहते हैं वह एक सेफफोर एक शर्त चर नहीं है।

एक सेमफोर राज्य बनाए रखता है और इसके खिलाफ प्रतीक्षा() और सिग्नल() की गणना करता है।
इसे आमतौर पर एक शर्त चर का उपयोग करके लागू किया जाता है।

एक छोटे कार्यान्वयन के लिए here देखें।