2009-06-16 10 views
6

क्या पहले mutex पर लॉक लेने के बिना pthread_cond_timedwait को कॉल करने के लिए कोई नकारात्मक पक्ष है, और pthread_cond_signal को कॉल करते समय म्यूटेक्स लॉक भी नहीं ले रहा है?pthread_cond_timedwait और pthread_cond_signal (लिनक्स पर) के लिए mutex लॉक नहीं करना

मेरे मामले में वास्तव में जांच करने की कोई शर्त नहीं है, मैं जावा प्रतीक्षा (लंबी) और सूचित() के समान व्यवहार चाहता हूं।

दस्तावेज़ीकरण के अनुसार, "अप्रत्याशित शेड्यूलिंग व्यवहार" हो सकता है। मुझे यकीन नहीं है कि इसका क्या अर्थ है।

एक उदाहरण प्रोग्राम म्यूटेक्स को लॉक किए बिना ठीक काम करता प्रतीत होता है।

+0

बस स्पष्ट होने के लिए, आप क्या चाहते हैं एन सेक तक इंतजार करना है, जब तक कि आप जल्दी से जागृत न हों? –

+0

हाँ बस यही। शायद सेफफोर्स एक बेहतर सौदा है। –

उत्तर

11

पहले ठीक नहीं है:

pthread_cond_timedwait() और pthread_cond_wait() कार्यों करेगा एक शर्त चर पर ब्लॉक। वे को कॉलिंग थ्रेड या अपरिभाषित व्यवहार परिणामों द्वारा लॉक किए गए म्यूटेक्स के साथ बुलाया जाएगा।

http://opengroup.org/onlinepubs/009695399/functions/pthread_cond_timedwait.html

कारण यह है कि कार्यान्वयन म्युटेक्स पर भरोसा करने के क्रम में सुरक्षित रूप से एक वेटर सूची में जोड़ने के लिए में बंद किया जा रहा चाहते हो सकता है। और यह बिना किसी जांच के म्यूटेक्स को रिलीज़ करना चाह सकता है।

दूसरा परेशान करने वाला है:

अगर उम्मीद के मुताबिक समय-निर्धारण व्यवहार की आवश्यकता है, तो उस म्युटेक्स द्वारा धागा pthread_cond_signal() या pthread_cond_broadcast() बुला बंद है।

http://www.opengroup.org/onlinepubs/007908775/xsh/pthread_cond_signal.html

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

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

Btw, जावा में आप को सूचित करने() या notifyAll() में ताला लगा है करने के लिए है:

यह विधि केवल एक धागा इस वस्तु के मॉनिटर के मालिक है कि द्वारा बुलाया जाना चाहिए ।

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#notify()

जावा सिंक्रनाइज़ {/}/प्रतीक्षा/notifty/notifyAll व्यवहार/pthread_mutex_unlock/pthread_cond_wait/pthread_cond_signal/pthread_cond_broadcast, और नहीं द्वारा संयोग pthread_mutex_lock के अनुरूप है।

+0

आप जावाडॉक के लिंक को ठीक करना चाहते हैं ... कोष्ठक को यूआरएल का हिस्सा बनने की जरूरत है। –

+1

यदि थ्रेड थ्रेड के स्वामित्व में नहीं है तो जावा फेंकता है। – Arkadiy

+2

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

3

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

1

मुझे लगता है कि यह (अपरीक्षित कोड ध्यान दें) काम करना चाहिए:

// initialize a semaphore 
sem_t sem; 
sem_init(&sem, 
    0, // not shared 
    0 // initial value of 0 
    ); 


// thread A 
struct timespec tm; 
struct timeb tp; 

const long sec  = msecs/1000; 
const long millisec = msecs % 1000; 

ftime(&tp); 
tp.time += sec; 
tp.millitm += millisec; 
if(tp.millitm > 999) { 
    tp.millitm -= 1000; 
    tp.time++; 
} 
tm.tv_sec = tp.time; 
tm.tv_nsec = tp.millitm * 1000000; 

// wait until timeout or woken up 
errno = 0; 
while((sem_timedwait(&sem, &tm)) == -1 && errno == EINTR) { 
    continue; 
} 

return errno == ETIMEDOUT; // returns true if a timeout occured 


// thread B 
sem_post(&sem); // wake up Thread A early 
+0

+1, हालांकि सावधान रहें कि sem_timed_wait वैकल्पिक है। जिसके द्वारा मेरा मतलब सेमफोरों से अधिक वैकल्पिक है, जो स्वयं भी वैकल्पिक हैं लेकिन उनके बिना pthreads बहुत अधिक बिंदु नहीं है ... –

-1

"अप्रत्याशित शेड्यूलिंग व्यवहार" सिर्फ इतना है कि इसका मतलब है। आप नहीं जानते कि क्या होने जा रहा है। न ही कार्यान्वयन करें। यह उम्मीद के रूप में काम कर सकता है। यह आपके ऐप को क्रैश कर सकता है। यह वर्षों से ठीक काम कर सकता है, फिर एक दौड़ की स्थिति आपके ऐप को बंदर बनाती है। यह deadlock सकता है।

मूल रूप से कोई भी दस्तावेज़ कुछ भी अपरिभाषित सुझाव देते हैं/unpredicatble भी हो सकता है जब तक कि आप क्या डॉक्स आपको बता करने के लिए करते हैं, तो आप बेहतर करते हैं। अन्य चीजें आपके चेहरे में उड़ा सकती हैं। (और यह तब तक उड़ाएगा जब तक कि आप कोड को उत्पादन में न डाल दें, बस आपको और भी परेशान करने के लिए। कम से कम यह मेरा अनुभव है)

+2

मैं सहमत नहीं हूं। "अप्रत्याशित शेड्यूलर व्यवहार" का अर्थ संदिग्ध है, लेकिन मुझे पूरा यकीन है कि इरादा "अपरिभाषित व्यवहार" को इंगित नहीं करना है, या उन्होंने कहा होगा कि वे pthread_cond_wait में करते हैं। –

9

बुटेनहोफ उत्कृष्ट "पॉज़िक्स थ्रेड के साथ प्रोग्रामिंग" अध्याय 3.3 के अंत में इस अधिकार पर चर्चा करता है .3।

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

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

+0

+1 छद्म के अच्छे स्पष्टीकरण के लिए "मुझे म्यूटेक्स को हालत सिग्नलिंग के लिए क्यों लॉक करना चाहिए?" मुद्दा! –

+0

म्यूटेक्स लॉक के बिना कन्वेयर को सिग्नल करना सिर्फ एक संभावित अनुकूलन नहीं है। आप लॉक से सैकड़ों अनावश्यक मशीन चक्र ले रहे हैं। – Kaz

+0

@ काज़: हाँ आप लॉक से मशीन चक्र निकाल रहे हैं और सूक्ष्म स्तर पर अनुकूलित कर चुके हैं, लेकिन यदि आप प्राथमिकता-उलटा परिणामस्वरूप हैं और आपका उच्च प्राथमिकता धागा निचले प्राथमिकता वाले थ्रेड पर प्रतीक्षा कर रहा है, तो आपके पास शायद उप-इष्टतम कार्यक्रम। – TheJuice

0

जब भी संभव हो, म्यूटेक्स के बाहर स्थितियों को संकेत दिया जाना चाहिए। म्यूटेक्स समवर्ती प्रोग्रामिंग में एक आवश्यक बुराई है। उनका उपयोग विवाद की ओर जाता है जो एकाधिक प्रोसेसर के उपयोग से प्राप्त अधिकतम प्रदर्शन की प्रणाली को लूटता है।

एक म्युटेक्स के प्रयोजन के कार्यक्रम में कुछ साझा चर के लिए उपयोग की रक्षा के लिए इतना है कि वे atomically व्यवहार करते है। जब एक म्यूटेक्स के अंदर एक सिग्नलिंग ऑपरेशन किया जाता है, तो यह म्यूटेक्स में सैकड़ों अप्रासंगिक मशीन चक्रों को शामिल करने का कारण बनता है, जिसमें साझा डेटा की रक्षा करने के लिए कुछ भी नहीं है। संभावित रूप से, यह किसी उपयोगकर्ता स्थान से कर्नेल में सभी तरह से कॉल करता है।

मानक में "अनुमानित शेड्यूलर व्यवहार" के बारे में नोट पूरी तरह से फर्जी हैं।

जब हम मशीन को अनुमानित, अच्छी तरह से परिभाषित क्रम में बयानों को निष्पादित करना चाहते हैं, तो उसके लिए उपकरण निष्पादन के एक थ्रेड के भीतर विवरणों का अनुक्रमण है: S1 ; S2। विवरण S1S2 से पहले "निर्धारित" है।

हम धागे का उपयोग करते हैं जब हम महसूस करते हैं कि कुछ क्रियाएं स्वतंत्र हैं और उनका शेड्यूलिंग ऑर्डर महत्वपूर्ण नहीं है, और वास्तविक समय की घटनाओं या एकाधिक प्रोसेसर पर कंप्यूटिंग के लिए अधिक समय पर प्रतिक्रिया की तरह प्रदर्शन लाभ प्राप्त किए जा सकते हैं।

कई बार जब कई धागे के बीच शेड्यूलिंग ऑर्डर महत्वपूर्ण हो जाते हैं, तो यह प्राथमिकता नामक अवधारणा के तहत आता है। प्राथमिकता हल करती है कि पहले क्या होता है जब एन कथन में से कोई भी संभावित रूप से निष्पादित करने के लिए निर्धारित किया जा सकता है। मल्टीथ्रेडिंग के तहत ऑर्डर करने के लिए एक अन्य टूल क्यूइंग है। घटनाओं को एक या अधिक धागे से कतार में रखा जाता है और एक एकल सेवा धागा कतार क्रम में घटनाओं को संसाधित करता है।

नीचे की रेखा है, pthread_cond_broadcast की नियुक्ति निष्पादन आदेश को नियंत्रित करने के लिए एक उपयुक्त उपकरण नहीं है। यह निष्पादन आदेश को इस अर्थ में अनुमानित नहीं करेगा कि कार्यक्रम अचानक एक ही है, हर मंच पर पुनरुत्पादित व्यवहार।

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