मैं C ++ 11 में थ्रेड को कैसे समाप्त कर सकता हूं?


137

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


7
यहाँ इस विषय पर अच्छा सवाल है: stackoverflow.com/questions/2790346/c0x-thread-interruption "सभी भाषा विनिर्देश कहते हैं कि समर्थन भाषा में नहीं बनाया गया है"
निमंजा बोरिक

जवाबों:


138
  1. आप std::terminate()किसी भी थ्रेड से कॉल कर सकते हैं और जिस थ्रेड का आप ज़िक्र कर रहे हैं वह बलपूर्वक समाप्त हो जाएगा।

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

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

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

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

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

एक std::threadइस सदस्य कार्य हो सकता है:

native_handle_type native_handle();

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


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

6
आप कॉल exit()या abort()एक ही समग्र प्रभाव के लिए भी कर सकते हैं ।
एन। 'सर्वनाम' मी।

2
# 1 एक मजाक है और @ क्रिसडोड सही है। # 3 के तहत पहले वाक्य में जवाब में मजाक समझाया गया है। नन्नो लैंगस्ट्रेट का जवाब और इसके नीचे की टिप्पणियों को भी देखें।
हावर्ड हिनांट

43

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

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


14
आह, मेरा # 1 वास्तव में अजीब है। आपको यह निर्दिष्ट करने की आवश्यकता नहीं है कि आप किस थ्रेड को जबरदस्ती समाप्त करना चाहते हैं। सिस्टम सिर्फ जादुई रूप से जानता है कि आप किसको जबरदस्ती खत्म करना चाहते हैं और यह करता है!
हावर्ड हिनांत

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

2
बस निर्दोष C ++ नौसिखियों को अपनी आशाओं को बहुत दूर / बहुत लंबे समय तक रोकने से रोकना होगा।
नन्नो लैंगस्ट्रेट

2
सुरुचिपूर्ण ढंग से कहा गया। :-)
हावर्ड हिनांत

@NannoLangstraat dammnit ... मुझे ऐसी उच्च उम्मीदें थीं, जब तक मैंने पढ़ा: (.. आलोल, ओह वेल + 1 के चारों ओर
:)

13

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

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

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

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

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


8
यह बहुत उपयोगी उत्तर नहीं है। मल्टी-प्रोसेसिंग यहाँ प्रासंगिक नहीं है, और मल्टी-थ्रेडिंग के बारे में अवलोकन व्यापक हैं।
मर्सल्ट्स

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

C # में यह सुविधा है।
डेरफ स्केन

@Derf Skren "वास्तव में कोई भी भाषा या कोई भी ऑपरेटिंग सिस्टम नहीं है जो आपको बिना उपयोग के चेतावनी के अतुल्यकालिक थ्रेड समाप्ति के लिए सुविधाएं प्रदान करता है" (c) जरथुस्सा "टिप्पणी: महत्वपूर्ण! थ्रेड.आर्ट विधि का उपयोग सावधानी के साथ किया जाना चाहिए! विशेष रूप से जब आप इसे वर्तमान थ्रेड के अलावा किसी थ्रेड को निरस्त करने के लिए कहते हैं, तो आप नहीं जानते कि कौन सा कोड निष्पादित किया गया है या निष्पादित करने में विफल रहा है ... "(c) Microsoft लिंक: docs.microsoft.com/en-us/dotnet/ एपीआई /…
जरथुस्सोए

11

C ++ थ्रेड को समाप्त करने के लिए OS पर निर्भर फ़ंक्शन का उपयोग करने की युक्तियां:

  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


5

मुझे लगता है कि जिस धागे को मारने की जरूरत है, वह या तो किसी भी तरह के वेटिंग मोड में है, या कोई भारी काम कर रहा है। मैं एक "भोले" तरीके का उपयोग करने का सुझाव दूंगा।

कुछ वैश्विक बूलियन को परिभाषित करें:

std::atomic_bool stop_thread_1 = false;

निम्नलिखित कोड (या समान) को कई प्रमुख बिंदुओं में रखें, इस तरह से यह कॉल स्टैक में सभी कार्यों का कारण बनेगा जब तक कि धागा स्वाभाविक रूप से समाप्त न हो जाए:

if (stop_thread_1)
    return;

फिर धागे को दूसरे (मुख्य) धागे से रोकने के लिए:

stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.