स्थानीय स्थिर चर प्रारंभिकरण सी ++ 11 में थ्रेड-सुरक्षित है?

मुझे पता है कि यह अक्सर पूछे जाने वाले प्रश्न हैं, लेकिन जैसा कि बहुत सारे रूप हैं, मैं इसे फिर से बता देना चाहता हूं, और उम्मीद है कि वर्तमान स्थिति को प्रतिबिंबित करने का उत्तर होगा। कुछ इस तरह

Logger& g_logger() {
    static Logger lg;
    return lg;
}

परिवर्तनीय एलजी का कन्स्ट्रक्टर केवल एक बार चलाने की गारंटी है?

मुझे पिछले उत्तरों से पता है कि सी ++ 03 में, यह नहीं है; सी ++ 0 एक्स ड्राफ्ट में, यह लागू किया जाता है। लेकिन मुझे एक स्पष्ट जवाब चाहिए

  1. सी ++ 11 मानक (ड्राफ्ट नहीं) में, थ्रेड-सुरक्षित प्रारंभिक व्यवहार अंतिम रूप दिया गया है?
  2. यदि उपर्युक्त हां है, लोकप्रिय कंपाइलरों के वर्तमान नवीनतम रिलीज में, अर्थात् जीसीसी 4.7, वीसी 2011 और क्लैंग 3.0, क्या वे सही ढंग से कार्यान्वित किए गए हैं?
179
क्या यह वीएस2013 में सुरक्षित है अगर हम सुनिश्चित करते हैं कि किसी भी अन्य थ्रेड चलने से पहले g_logger को मुख्य() से एक बार बुलाया जाता है?
जोड़ा लेखक paulm, स्रोत
विजुअल स्टूडियो 2012 अपडेट 3 इसका समर्थन नहीं करता है - मैंने इसे एक छोटे परीक्षण कार्यक्रम के साथ परीक्षण किया और असेंबली कोड को देखा।
जोड़ा लेखक Tobias Langner, स्रोत
क्या मैं इस तरह के एक समारोह के उद्देश्य से पूछ सकता हूं? एक साधारण वैश्विक लॉगर g_logger; पर इसका क्या फायदे हैं
जोड़ा लेखक Chris Lutz, स्रोत
@ बाल्कि, जीसीसी ने इसे लगभग एक दशक तक लागू किया है। क्लैंग भी इसका समर्थन करता है।
जोड़ा लेखक Jonathan Wakely, स्रोत
@Chris: स्थिर प्रारंभिक आदेश fiasco की निर्धारण प्रारंभिक शुरुआत और टालना। स्थानीय स्टेटिक्स को पहली बार प्रारंभ किया जाएगा जब फ़ंक्शन को पहली बार बुलाया जाता है।
जोड़ा लेखक Xeo, स्रोत
दूसरे प्रश्न के लिए, अभी तक कोई कंपाइलर इसे कार्यान्वित नहीं किया है।
जोड़ा लेखक balki, स्रोत
अंततः "जादू सांख्यिकी" वीएस 2015 के साथ आ रहे हैं: blogs.msdn.com/b/vcblog/archive/2014/11/17/…
जोड़ा लेखक mlvljr, स्रोत
धन्यवाद Xeo, यह मुख्य कारण है। कुछ अन्य में शामिल हैं: 1. आम तौर पर लॉगिंग सिस्टम में, क्लाइंट कोड मैक्रो के रूप में इसका उपयोग करता है, जैसे LOG << "आपका लॉग" ..., और मैक्रोज़ को लॉगर 2 के लिए एक निश्चित पहुंच प्राप्त करना होता है। लॉगर नहीं बनाया गया है यदि आप इसका उपयोग नहीं करते हैं। 3. आप शायद अपने क्लाइंट को एकाधिक लॉगर्स नहीं बनाना चाहते हैं (सिंक्रनाइज़ेशन इश्यू, इत्यादि हैं ...) ताकि लॉगर का निजी कन्स्ट्रक्टर हो, जो केवल दोस्त g_logger() द्वारा पहुंचा जा सकता है
जोड़ा लेखक Ralph Zhang, स्रोत
न ही, यह दिखाई देता है, विजुअल स्टूडियो 2013 होगा। msdn.microsoft.com/en-us/library/vstudio/…
जोड़ा लेखक rkjnsn, स्रोत

2 उत्तर

प्रासंगिक खंड 6.7:

इस तरह के चर को पहली बार नियंत्रण घोषित किया जाता है, इसकी घोषणा के माध्यम से; इस तरह के एक चर को प्रारंभिकता के पूरा होने पर शुरू किया जाता है। [...] यदि नियंत्रण प्रारंभिक रूप से घोषणापत्र प्रारंभ होने पर घोषणा में प्रवेश करता है, तो समवर्ती निष्पादन प्रारंभिक समापन के लिए प्रतीक्षा करेगा।

फिर एक फुटनोट है:

कार्यान्वयन को प्रारंभकर्ता के निष्पादन के आसपास किसी भी डेडलॉक को लागू नहीं करना चाहिए।

तो हाँ, आप सुरक्षित हैं।

(यह संदर्भ के माध्यम से चर के बाद की पहुंच के बारे में निश्चित रूप से कुछ भी नहीं कहता है।)

160
जोड़ा
यह ध्यान रखना महत्वपूर्ण है कि स्थिर लॉगर lg; केवल थ्रेड-सुरक्षित है यदि लॉगर का डिफ़ॉल्ट कन्स्ट्रक्टर थ्रेड-सुरक्षित है, यानी यह किसी भी संशोधित साझा संसाधन तक नहीं पहुंचता है आंतरिक रूप से, वैश्विक चर या सिंगलेट्स के माध्यम से कहते हैं। यह ध्यान दिया जाना चाहिए कि मानक गारंटी देता है केवल यह: यदि एक और थ्रेड कन्स्ट्रक्टर को एक साथ निष्पादित करना शुरू करने का प्रयास करता है, तो उनमें से केवल एक ही वास्तव में इसे निष्पादित करेगा, शेष प्रतीक्षा करेंगे प्रारंभिक समापन के लिए। मानक, हालांकि, निर्माता के थ्रेड-सुरक्षा की कोई गारंटी नहीं देता है।
जोड़ा लेखक Nawaz, स्रोत
@ केरेकस्क: मैंने यह भी समझाया है कि मेरा क्या मतलब है: यानी यह किसी भी संशोधित साझा संसाधन आंतरिक रूप से तक नहीं पहुंचता है। सिर्फ इसलिए कि केवल एक धागा एक कन्स्ट्रक्टर निष्पादित करता है, इसका मतलब यह नहीं है कि यह क्या करता है थ्रेड-सुरक्षित है। यदि यह असुरक्षित साझा संसाधन को संशोधित करता है, तो यह थ्रेडसेफ नहीं होगा।
जोड़ा लेखक Nawaz, स्रोत
@ नवाज: कन्स्ट्रक्टर को थ्रेड-सुरक्षित क्यों होना चाहिए? आपने खुद कहा था कि केवल एक धागा कन्स्ट्रक्टर निष्पादित करेगा।
जोड़ा लेखक Kerrek SB, स्रोत
@ नवाज: अच्छा, यह सच है, लेकिन यह भी एक पूर्ण सामान्यता है: साझा डेटा की समवर्ती पहुंच को सिंक्रनाइज़ किया जाना चाहिए। मुझे नहीं लगता कि इस बात का कोई सुझाव है कि स्थैतिक प्रारंभिकरण किसी भी तरह से उस नियम से छूट प्रदान करेगा, इसलिए मुझे विशेष रूप से कॉल करने के लायक नहीं लगता था।
जोड़ा लेखक Kerrek SB, स्रोत
एक शर्म की बात है कि न तो यह सवाल और न ही जवाब "मेयर्स सिंगलटन" वाक्यांश का जिक्र है
जोड़ा लेखक Nemo, स्रोत
इसके अलावा, यह चर के पाठकों के बारे में कुछ भी नहीं कहता है, जिसका अर्थ है कि आपके पास टीएसएएन मुद्दे हो सकते हैं यदि आपके पास स्थिर निर्माता द्वारा पहले से कोई पाठक नहीं है। बेशक, यदि आप उपरोक्त पैटर्न का उपयोग करते हैं (foo और GetFooLog() {static foo bar; वापसी बार;} तो टीएसएएन समस्या उत्पन्न नहीं होती है।
जोड़ा लेखक jesup, स्रोत
जोड़ा लेखक Ion Todirel, स्रोत

- नोनो-थ्रेडसेफ-स्टेटिक्स भी उल्लेखनीय लायक है। जीसीसी में:

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

Also, have a look at the old thread Are function static variables thread-safe in GCC?

9
जोड़ा