क्या यह बढ़ावा देने के लिए स्मार्ट है :: थ्रेड और बूस्ट :: म्यूटेक्स सी ++ 11 समकक्षों के साथ?


153

प्रेरणा: कारण कि मैं इस पर विचार कर रहा हूं कि मेरे जीनियस प्रोजेक्ट मैनेजर को लगता है कि बूस्ट एक और निर्भरता है और यह भयानक है क्योंकि "आप इस पर निर्भर हैं" (मैंने बढ़ावा देने की गुणवत्ता को समझाने की कोशिश की, फिर कुछ समय बाद छोड़ दिया :( )। छोटा कारण है कि मैं यह करना चाहूंगा कि मैं सी + 11 सुविधाओं को सीखना चाहूंगा, क्योंकि लोग इसमें कोड शुरू करेंगे।

  1. क्या #include<thread> #include<mutex>समकक्षों के बीच 1: 1 मैपिंग और बूस्ट है?
  2. क्या आप सी ++ 11
    सामान के साथ बूस्ट सामान को बदलने के लिए एक अच्छा विचार करेंगे । मेरा उपयोग आदिम है, लेकिन क्या उदाहरण हैं जब std doesnt प्रस्ताव को बढ़ावा देता है? या (निन्दा) इसके विपरीत?

पीएस मैं जीसीसी का उपयोग करता हूं इसलिए हेडर हैं।


46
IMO Google कोडिंग दिशानिर्देश कई मायनों में मूर्ख हैं ... For eg। वे C ++ 11 से ऑटो की अनुमति नहीं देते ... :)
NoSenseEtAl

5
दिशा-निर्देश उद्धृत करना: [ऑटो] पठनीयता को बाधित करता है [क्योंकि यह हटाता है] जाँच की गई अतिरेक (जैसे नाम) जो पाठकों के लिए सहायक हो सकती है।
एंड्रयू टोमाज़ोस

31
for (auto it = v.begin () ... :)
NoSenseEtAl

15
@ एंड्रयूटोमेज़ोस-फथोमलिंग: वाक़ई? व्यक्तिगत रूप से मुझे नहीं लगता कि मैंने कभी भी वास्तविक प्रकार के इट्रेटर के बारे में ध्यान दिया है (अच्छी तरह से शायद कुछ समय), केवल समर्थित संचालन ... मेरा तर्क है कि वाक्यविन्यास अतिरेक शायद ही कभी एक अच्छा विचार (DRY) है।
ग्रिजली

16
btw google ने अपने गूंगे दिशानिर्देशों को संशोधित किया ताकि अब वे ऑटो
NoSenseEtAl

जवाबों:


192

Boost.Thread और C ++ 11 मानक थ्रेड लाइब्रेरी के बीच कई अंतर हैं:

  • बूस्ट धागा रद्दीकरण का समर्थन करता है, C ++ 11 धागे नहीं
  • C ++ 11 समर्थन करता है std::async, लेकिन बूस्ट नहीं करता है
  • बूस्ट में boost::shared_mutexमल्टीपल-रीडर / सिंगल-राइटर लॉकिंग है। अनुरूप std::shared_timed_mutexही सी ++ 14 (के बाद से उपलब्ध है N3891 ,), जबकि std::shared_mutexकेवल सी ++ 17 (के बाद से उपलब्ध है N4508 )।
  • C ++ 11 टाइमआउट बूस्ट टाइमआउट के लिए अलग हैं (हालांकि यह जल्द ही बदल जाना चाहिए अब Boost.Chrono को स्वीकार कर लिया गया है)।
  • कुछ नाम अलग हैं (जैसे boost::unique_futureबनाम std::future)
  • तर्क-पासिंग शब्दार्थ std::threadअलग - अलग हैं boost::thread--- बूस्ट का उपयोग करता है boost::bind, जिसके लिए प्रतिलिपि योग्य तर्कों की आवश्यकता होती है। std::threadइस तरह के std::unique_ptrतर्क के रूप में पारित किया जा करने के लिए केवल प्रकार की अनुमति देता है। के उपयोग के कारण boost::bind, प्लेसहोल्डर्स के शब्दार्थ जैसे कि _1नेस्टेड बाइंड एक्सप्रेशन अलग भी हो सकते हैं।
  • यदि आप स्पष्ट रूप से कॉल नहीं करते हैं join()या detach()फिर boost::threadविध्वंसक और असाइनमेंट ऑपरेटर detach()थ्रेड ऑब्जेक्ट को नष्ट / असाइन किए जाने पर कॉल करेगा । C ++ 11 std::threadऑब्जेक्ट के साथ, इससे std::terminate()एप्लिकेशन को कॉल और निरस्त किया जा सकेगा ।

मूव-ओनली पैरामीटर्स के बारे में बात को स्पष्ट करने के लिए, निम्नलिखित सी ++ 11 मान्य है, और नए थ्रेड शुरू intहोने पर अस्थायी std::unique_ptrसे पैरामीटर के स्वामित्व को स्थानांतरित करता f1है। हालाँकि, यदि आप उपयोग करते हैं boost::threadतो यह काम नहीं करेगा, क्योंकि यह boost::bindआंतरिक रूप से उपयोग करता है , और std::unique_ptrइसे कॉपी नहीं किया जा सकता है। GCC के साथ प्रदान की जाने वाली C ++ 11 थ्रेड लाइब्रेरी में एक बग भी है जो इस कार्य को रोकता है, क्योंकि यह std::bindकार्यान्वयन में भी उपयोग करता है।

void f1(std::unique_ptr<int>);
std::thread t1(f1,std::unique_ptr<int>(new int(42)));

यदि आप बूस्ट का उपयोग कर रहे हैं, तो आप संभवतः C ++ 11 थ्रेड्स में अपेक्षाकृत दर्द रहित रूप से स्विच कर सकते हैं यदि आपका कंपाइलर इसका समर्थन करता है (उदाहरण के लिए लिनक्स पर जीसीसी के हाल के संस्करणों में -std=c++0xमोड में उपलब्ध C ++ 11 थ्रेड लाइब्रेरी का ज्यादातर-पूरा कार्यान्वयन है)।

यदि आपका कंपाइलर C ++ 11 थ्रेड्स का समर्थन नहीं करता है, तो आप थर्ड-पार्टी कार्यान्वयन जैसे जस्ट :: थ्रेड प्राप्त करने में सक्षम हो सकते हैं , लेकिन यह अभी भी एक निर्भरता है।


1
पाठकों और लेखकों के लिए अलग-अलग लॉक / अनलॉक विधियाँ हैं ( lock/ unlockलेखकों के लिए / 'पाठकों के लिए' lock_sared / unlock_sared ')। कई पाठक बिना किसी अवरोध के लॉक_शेयर को कॉल कर सकते हैं, जब तक कि कोई भी लेखक इसका उपयोग नहीं कर रहा हो।
डेव एस

2
shared_mutexडॉक्स पर हैं boost.org/doc/libs/1_47_0/doc/html/thread/... । आप या तो म्यूटेक्स को साझा या अनन्य के रूप में लॉक करते हैं, और फिर संबंधित अनलॉक फ़ंक्शन का उपयोग करते हैं। तुम भी आरए II प्रकार का उपयोग यह करने के लिए (कर सकते हैं shared_lockएक साझा पढ़ ताला लेता है, और lock_guardऔर unique_lockएक विशेष ताला लेने के लिए)। मैंने केवल चाल के प्रकारों के बारे में बात स्पष्ट करने की कोशिश की है।
एंथनी विलियम्स

3
एक और छोटी सी बात जो मुझे उलझा देती है : बूस्ट में, एक रनिंग थ्रेड का डिस्ट्रॉयर इसे डिटैच कर देता है ( boost.org/doc/libs/1_47_0/doc/html/thread/… ), जबकि C ++ में, एक रनिंग थ्रेड कॉल्स का डिस्ट्रक्टर समाप्त हो जाता है () (FDIS 30.3.1.3)
क्यूबाई

3
C ++ 11 में, try_scoped_lockकार्यक्षमता द्वारा कवर किया गया है std::unique_lock। एक कंस्ट्रक्टर है जो म्यूटेक्स लेता है और std::try_to_lock, try_lock()इसके बजाय म्यूटेक्स पर कॉल करेगा lock()। देखें stdthread.co.uk/doc/headers/mutex/unique_lock/…
एंथनी विलियम्स

4
हां, Boost.Thread C ++ 11 मानक के बहुत करीब हो गया है क्योंकि मैंने इसे लिखा था, मुख्यतः विसेंट बोटेट के काम के कारण।
एंथनी विलियम्स

24

std::threadकुछ अंतरों केboost::thread साथ बड़े पैमाने पर बाद में मॉडलिंग की जाती है :

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

यह 2007 से है, इसलिए कुछ बिंदु अब मान्य नहीं हैं: boost::threadअब एक native_handleफ़ंक्शन है, और, जैसा कि टिप्पणीकार बताते हैं, std::threadअब रद्द नहीं होता है।

मुझे boost::mutexऔर के बीच कोई महत्वपूर्ण अंतर नहीं मिला std::mutex


2
std::threadरद्दीकरण नहीं है; यह है boost::threadकि करता है!
एंथनी विलियम्स

@Anthony क्या आप सुनिश्चित हैं कि आप interrupt()को बढ़ावा देने के लिए मतलब नहीं है :: धागा? यह भी प्रतीत होता है कि यह एक मूल प्रस्ताव है, जो 2007 से बदल गया है।
एलेक्स बी

4
हां, को रद्द करने को "रुकावट" कहा जाता है। हां, यह एक पुराना प्रस्ताव है। C ++ 11 मानक (जिसमें थ्रेड लाइब्रेरी शामिल है) का नवीनतम सार्वजनिक मसौदा खुला
एंथनी विलियम्स

6

पलायन न करने का एक कारण है std::thread

यदि आप स्थैतिक लिंकिंग का उपयोग कर रहे हैं, तो std::threadइन gcc बग्स / सुविधाओं के कारण अनुपयोगी हो जाता है:

अर्थात्, यदि आप फोन करते हैं std::thread::detachया std::thread::joinयह अपवाद या दुर्घटना को जन्म देगा, जबकि boost::threadइन मामलों में ठीक काम करता है।


मैं देखता हूं कि एक बग UNCONFIRMED है और दूसरा INVALID है, जिसमें एक टिप्पणी है जिसमें कहा गया है कि रिपोर्टर को इसके खिलाफ लिंक होना चाहिए libpthread.a। क्या तुम बिल्कुल यकीन है कि तुम क्या कह रहे हो?
einpoklum

1
@einpoklum, आपको इसका उपयोग करके काम करने में सक्षम होना चाहिए Wl,--whole-archive -lpthread -Wl,--no-whole-archive, उदाहरण के लिए इस उत्तर को देखें stackoverflow.com/a/23504509/72178 । लेकिन यह लिंक करने का बहुत सीधा तरीका नहीं है libpthread.aऔर इसे बुरा विचार भी माना जाता है।
ks1322

4
क्या हम मान सकते हैं कि ये कीड़े अब ठीक हो गए हैं क्योंकि यह अब 2016 है? 2012 में बग्स को पोस्ट किया गया था और यह 4.9.2 से, यह आधिकारिक तौर पर C ++ 11 का समर्थन करता है, इसलिए हम आधिकारिक समर्थन से पहले C ++ 11 की शिकायत नहीं कर सकते हैं।
स्पलैश

6

एंटरप्राइज केस

यदि आप उस एंटरप्राइज़ के लिए सॉफ़्टवेयर लिख रहे हैं, जिसे मध्यम से बड़ी ऑपरेटिंग सिस्टम पर चलाने की आवश्यकता है और परिणामस्वरूप उन ऑपरेटिंग सिस्टम पर विभिन्न प्रकार के कंपाइलर और कंपाइलर संस्करण (विशेषकर अपेक्षाकृत पुराने वाले) बनाए जाते हैं, तो मेरा सुझाव इससे दूर रहना है C ++ 11 अब के लिए पूरी तरह से। इसका मतलब है कि आप उपयोग नहीं कर सकते std::thread, और मैं उपयोग करने की सलाह दूंगाboost::thread

बेसिक / टेक स्टार्टअप केस

यदि आप एक या दो ऑपरेटिंग सिस्टम के लिए लिख रहे हैं, तो आप यह सुनिश्चित करने के लिए जानते हैं कि आपको कभी भी एक आधुनिक कंपाइलर के साथ निर्माण करना होगा जो ज्यादातर C ++ 11 (जैसे VS2015, GCC 5.3, Xcode 7) का समर्थन करता है, और आप पहले से ही नहीं हैं बूस्ट लाइब्रेरी पर निर्भर है, तो std::threadएक अच्छा विकल्प हो सकता है।

मेरा अनुभव

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


1
@UmNyobe हालांकि वह सही है। C ++ 11 थ्रेडिंग के कई कार्यान्वयन इतने टूटे हुए हैं कि मुझे आश्चर्य है कि लोग इसका उपयोग करने पर भी विचार करते हैं।
स्टेसीगर्ल

3

विजुअल स्टूडियो 2013 के साथ std::mutexलगता है की तुलना में अलग व्यवहार करते हैं boost::mutex, जिससे मुझे कुछ समस्याएं हुईं ( यह प्रश्न देखें )।


1

Std के संबंध में :: साझा_मुटेक्स C ++ 17 में जोड़ा गया

यहाँ अन्य उत्तर सामान्य रूप से अंतर का बहुत अच्छा अवलोकन प्रदान करते हैं। हालाँकि, वहाँ कई मुद्दों के साथ std::shared_mutexकि बढ़ावा देने के हल कर रहे हैं।

  1. अपग्रेड करने योग्य म्यूटेशन। ये अनुपस्थित हैं std::thread। वे एक पाठक को किसी अन्य लेखक को आपके सामने लाने की अनुमति के बिना एक लेखक को अपग्रेड करने की अनुमति देते हैं । ये आपको पूर्व-प्रक्रिया की एक बड़ी गणना (उदाहरण के लिए, डेटा संरचना reindexing) जैसी चीज़ों को करने की अनुमति देते हैं, जब रीड मोड में होते हैं, तो थोड़े समय के लिए केवल राइट लॉक को दबाए रखते हुए रीडेक्स को लागू करने के लिए लिखने के लिए अपग्रेड करें।

  2. निष्पक्षता। यदि आपके पास लगातार पढ़ने की गतिविधि है std::shared_mutex, तो आपके लेखक अनिश्चित काल के लिए नरम हो जाएंगे। ऐसा इसलिए है क्योंकि अगर कोई अन्य पाठक साथ आता है, तो उन्हें हमेशा प्राथमिकता दी जाएगी। boost:shared_mutexसभी धागे के साथ , अंततः प्राथमिकता दी जाएगी। (१) न तो पाठक और न ही लेखक भूखे रहेंगे।

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

(1) इसका उपयोग करने वाला वास्तविक एल्गोरिथ्म ओएस थ्रेड अनुसूचक पर आधारित है। मेरे अनुभव में, जब रीड्स संतृप्त होते हैं, तो OSX या लिनक्स की तुलना में विंडोज पर लंबे समय तक विराम (राइट लॉक प्राप्त करने पर) होते हैं।


0

मैंने बढ़ावा देने के बजाय std से share_ptr का उपयोग करने की कोशिश की और मुझे वास्तव में इस वर्ग के जीसीसी कार्यान्वयन में एक बग मिला। मेरे एप्लिकेशन को दो बार बुलाया विध्वंसक के कारण दुर्घटनाग्रस्त हो गया (यह वर्ग थ्रेड-सुरक्षित होना चाहिए और इस तरह की समस्याएं उत्पन्न नहीं होनी चाहिए)। बढ़ावा देने के लिए आगे बढ़ने के बाद :: साझा_प्राप्त सभी समस्याएं गायब हो गईं। C ++ 11 के वर्तमान कार्यान्वयन अभी भी परिपक्व नहीं हैं।

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

योग करने के लिए - यदि आपके पास पहले से ही बूस्ट का उपयोग करते हुए लिखा गया है, तो यह आपके कोड को सुरक्षित रखने के लिए सुरक्षित है क्योंकि यह C ++ 11 मानक पर जाने में कुछ प्रयास लगाने के बजाय है।


4
shared_ptrनाशक धागा सुरक्षित होने की जरूरत नहीं है, यह के अपरिभाषित व्यवहार एक धागा एक वस्तु तक पहुंच के दौरान एक और धागा इसे नष्ट कर रहा है है। यदि आपको लगता है कि आपको जीसीसी के शेयर्ड_प्ट्र में बग मिल गया है , तो कृपया इसकी रिपोर्ट करें , अन्यथा संभावना के संतुलन पर आप इसका गलत उपयोग कर रहे हैं।
जोनाथन वेकली
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.