2012-08-31 12 views
81

मुझे धागे को सही ढंग से समाप्त करने की आवश्यकता नहीं है, या इसे "टर्मिनेट" कमांड का जवाब देना है। मैं शुद्ध सी ++ 11 का उपयोग करके जोर से थ्रेड को समाप्त करने में रूचि रखता हूं।मैं सी ++ 11 में थ्रेड कैसे समाप्त करूं?

+7

यहां इस विषय पर अच्छा सवाल है: http://stackoverflow.com/questions/2790346/c0x-thread-interruption "सभी भाषा विनिर्देश कहता है कि समर्थन नहीं बनाया गया है झूठ में आयु " –

उत्तर

88
  1. आप किसी भी धागा और धागे आप जबरदस्ती खत्म हो जाएगा संदर्भ दे रहे से std::terminate() कह सकते हैं।

  2. आप ~thread() के लिए व्यवस्था कर सकता है एक उस वस्तु पर हस्तक्षेप join() है और न ही detach() बिना, लक्ष्य धागे की वस्तु पर निष्पादित किया जाना है। इसका विकल्प 1 के रूप में भी होगा।

  3. आप एक अपवाद तैयार कर सकते हैं जिसमें एक विनाशक है जो अपवाद फेंकता है। और फिर इस अपवाद को फेंकने के लिए लक्ष्य धागे की व्यवस्था करें जब इसे बलपूर्वक समाप्त किया जाए। इस अपवाद को फेंकने के लिए इस पर मुश्किल हिस्सा लक्ष्य धागा प्राप्त कर रहा है।

विकल्प 1 और 2 इंट्रा-प्रक्रिया संसाधन रिसाव नहीं है, लेकिन वे हर धागा समाप्त।

विकल्प 3 शायद संसाधनों को रिसाव करेगा, लेकिन आंशिक रूप से सहकारी है कि लक्षित धागे को अपवाद फेंकने के लिए सहमत होना है।

सी ++ 11 में कोई पोर्टेबल तरीका नहीं है (जिसे मैं जानता हूं) गैर-सहकारी रूप से एक बहु थ्रेड प्रोग्राम (यानी सभी धागे को मारने के बिना) में एक थ्रेड को मारने के लिए कोई पोर्टेबल तरीका नहीं है। ऐसी सुविधा डिजाइन करने के लिए कोई प्रेरणा नहीं थी।

native_handle_type native_handle(); 

आप इस का उपयोग करने के लिए आप क्या चाहते करने के लिए एक ओएस पर निर्भर समारोह कॉल करने के लिए सक्षम हो सकता है:

एक std::thread इस सदस्य कार्य हो सकता है। उदाहरण के लिए ऐप्पल के ओएस पर, यह फ़ंक्शन मौजूद है और native_handle_typepthread_t है। यदि आप सफल हैं, तो आप संसाधनों को रिसाव करने की संभावना रखते हैं।

+56

-1' std :: terminate' प्रोग्राम को समाप्त करने, सभी धागे को मारता है ... –

+43

@ChrisDodd काउंटर +1, वही है जो वह अपने जवाब में लिखता है। – inf

+1

_ "इंट्रा-प्रोसेस संसाधनों को रिसाव न करें" पर थोड़ा नाइटपिक _: हालांकि यह निश्चित रूप से सच है कि ओएस प्रक्रिया को मारने के बाद सभी संसाधनों को पुनः प्राप्त कर लेगा, संसाधनों के संबंध में संसाधन _are_ लीक हो गए हैं। यह आमतौर पर अप्रासंगिक है, लेकिन कुछ मामलों में अभी भी एक मुद्दा हो सकता है। 'std :: terminate' न तो स्थैतिक विनाशकों को बुलाता है और न ही यह आउटपुट बफर फ्लश करता है, इसलिए जिस क्रम में संसाधन जारी किए जाते हैं, वह अच्छी तरह परिभाषित नहीं है, और न ही आपको कोई गारंटी है कि आपका कोई भी डेटा उपयोगकर्ता या लिखित में दिखाई देता है स्थायी स्टोर, या यहां तक ​​कि लगातार और पूर्ण करने के लिए। – Damon

25

@ हावर्ड हिनंट का जवाब सही और दोनों सही है। लेकिन अगर यह बहुत जल्दी पढ़ा जाता है तो इसे गलत समझा जा सकता है, क्योंकि std::terminate() (पूरी प्रक्रिया) का नाम "समाप्ति" के समान होता है जो @AlexanderVX को दिमाग में था (1 धागा)।

सारांश: "1 धागा + बलपूर्वक समाप्त करें (लक्ष्य धागा सहयोग नहीं करता है) + शुद्ध सी ++ 11 = कोई रास्ता नहीं।"

+7

आह, मेरा # 1 वास्तव में मजाकिया है।आपको यह निर्दिष्ट करने की ज़रूरत नहीं है कि आप किस धागे को मजबूती से समाप्त करना चाहते हैं। प्रणाली सिर्फ जादुई रूप से जानता है कि आप किसके लिए मजबूर होना चाहते हैं और यह करता है! –

+3

हां, 'std :: terminate()' answer क्लासिक शरारती डीजिन कहानी की तरह है; यह पत्र की ओपी की इच्छा में सबकुछ पूरा करता है, हालांकि शायद वह * जिस तरह से * नहीं था। कमजोर हास्य ने मुझे मुस्कुराया। :-) –

+0

बस निर्दोष सी ++ नौसिखियों को अपनी उम्मीदों को बहुत दूर/बहुत लंबा होने से रोकने के लिए है। –

4

इस प्रश्न में वास्तव में अधिक गहरी प्रकृति है और सामान्य रूप से बहु-विचारणीय अवधारणाओं की अच्छी समझ आपको इस विषय के बारे में जानकारी प्रदान करेगी। असल में कोई भी भाषा या कोई ऑपरेटिंग सिस्टम नहीं है जो आपको बिना किसी चेतावनी के अतुल्यकालिक अचानक थ्रेड समाप्ति के लिए सुविधाएं प्रदान करता है। और ये सभी निष्पादन वातावरण दृढ़ता से डेवलपर को सलाह देते हैं या सहकारी या तुल्यकालिक थ्रेड समाप्ति के आधार पर मल्टीथ्रेडिंग अनुप्रयोगों की भी आवश्यकता होती है। इस आम निर्णय और सलाह का कारण यह है कि वे सभी एक ही सामान्य मल्टीथ्रेडिंग मॉडल के आधार पर बनाए जाते हैं।

चलिए मल्टीप्रोसेसिंग और मल्टीथ्रेडिंग अवधारणाओं की तुलना दूसरे की फायदे और सीमाओं को बेहतर ढंग से समझने के लिए करते हैं।

मल्टीप्रोसेसिंग पूरे निष्पादन पर्यावरण को ऑपरेटिंग सिस्टम द्वारा नियंत्रित पूरी तरह से पृथक प्रक्रियाओं के सेट में विभाजित करता है।प्रक्रिया में निष्पादन पर्यावरण स्थिति शामिल है और प्रक्रिया के स्थानीय स्मृति और इसके अंदर डेटा और फाइल सिस्टम, सॉकेट, सिंक्रनाइज़ेशन ऑब्जेक्ट्स जैसे सभी सिस्टम संसाधन शामिल हैं। अलगाव प्रक्रिया की एक महत्वपूर्ण रूप से महत्वपूर्ण विशेषता है, क्योंकि यह प्रक्रिया सीमाओं द्वारा दोषों के प्रसार को सीमित करता है। दूसरे शब्दों में, कोई भी प्रक्रिया सिस्टम में किसी अन्य प्रक्रिया की स्थिरता को प्रभावित नहीं कर सकती है। प्रक्रिया व्यवहार के लिए भी यह सच है लेकिन कम प्रतिबंधित और अधिक धुंधला तरीके से। इस तरह के माहौल में किसी भी "मनमानी" पल में किसी भी प्रक्रिया को मार दिया जा सकता है, क्योंकि पहली बार प्रत्येक प्रक्रिया अलग होती है, दूसरी बात, ऑपरेटिंग सिस्टम के पास प्रक्रिया द्वारा उपयोग किए जाने वाले सभी संसाधनों के बारे में पूर्ण जानकारी होती है और उन्हें बिना लीक किए सभी को छोड़ दिया जा सकता है, और अंत में प्रक्रिया की जाएगी ओएस द्वारा वास्तव में मनमाने ढंग से पल में नहीं, बल्कि अच्छी तरह से परिभाषित बिंदुओं की संख्या में जहां प्रक्रिया की स्थिति अच्छी तरह से जाना जाता है।

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

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

+2

यह एक बहुत ही उपयोगी उत्तर नहीं है। बहु-प्रसंस्करण यहां प्रासंगिक नहीं है, और बहु-थ्रेडिंग के बारे में अवलोकन अपेक्षाकृत व्यापक हैं। – MSalters

+0

मैं जो कहना चाहता था और विवरण में कहा था कि बहुप्रवाह मॉडल बलपूर्वक थ्रेड समाप्ति का औपचारिक तरीका प्रदान नहीं करता है। सी ++ मेमोरी मॉडल, मल्टीथ्रेडिंग मॉडल इत्यादि सहित स्पष्ट मॉडल का पालन करना चाहता है। बलपूर्वक थ्रेड समाप्ति का तरीका स्वाभाविक रूप से असुरक्षित है। यदि सी ++ मानक समिति को इसे सी ++ में जोड़ने के लिए मजबूर किया जाएगा, तो इसे अगले कथन के साथ बनाया जाएगा "विधि समाप्त() थ्रेड निष्पादन को समाप्त करता है। व्यवहार अपरिभाषित।", जो कुछ जादू करेगा और (संभवतः) थ्रेड को समाप्त करता है "। – ZarathustrA

2

ओएस पर निर्भर फ़ंक्शन का उपयोग सी ++ धागा समाप्त करने के लिए के सुझाव:

  1. std::thread::native_handle() केवल join() या detach() कॉल करने से पहले धागे के वैध देशी संभाल प्रकार प्राप्त कर सकते हैं। उसके बाद, native_handle() रिटर्न 0 - pthread_cancel() coredump होगा।

  2. प्रभावी रूप से देशी धागा समाप्ति समारोह कॉल करने के लिए (जैसे pthread_cancel), आप std::thread::join() या std::thread::detach() कॉल करने से पहले देशी संभाल बचाने की जरूरत है। तो, जो आपकी मूल टर्मिनेटर हमेशा एक वैध देशी संभाल उपयोग करने के लिए किया है।

अधिक स्पष्टीकरण कृपया देखें: http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread

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