2014-10-09 10 views
9

मैं सी ++ में म्यूटेक्स के बारे में सीख रहा हूं और निम्नलिखित कोड (एन जोसुटिस 'से लिया गया है "सी ++ मानक लाइब्रेरी") में समस्या है।सी ++ प्रोग्राम अप्रत्याशित रूप से ब्लॉक/फेंकता

मुझे समझ नहीं आता क्यों यह ब्लॉक/फेंकता जब तक कि मैं मुख्य थ्रेड मेंthis_thread::sleep_for जोड़ने (तो यह ब्लॉक नहीं करता है और सभी तीन कॉल किया जाता है)।

कंपाइलर cl.exe कमांड लाइन से उपयोग किया जाता है।

#include <future> 
#include <mutex> 
#include <iostream> 
#include <string> 
#include <thread> 
#include <chrono> 

std::mutex printMutex; 

void print(const std::string& s) 
{ 
    std::lock_guard<std::mutex> lg(printMutex); 

    for (char c : s) 
    { 
     std::cout.put(c); 
    } 
    std::cout << std::endl; 
} 

int main() 
{ 
    auto f1 = std::async(std::launch::async, print, "Hello from thread 1"); 
    auto f2 = std::async(std::launch::async, print, "Hello from thread 2"); 

    // std::this_thread::sleep_for(std::chrono::seconds(1)); 

    print(std::string("Hello from main"));  
} 
+3

आप धागे को खत्म करने की प्रतीक्षा नहीं कर रहे हैं। मुझे लगता है कि यह एमएसवीसी लाइब्रेरी के साथ यहां एक मुद्दा है। – Niall

उत्तर

11

मुझे लगता है कि आप जो देख रहे हैं वह async के एमएसवीसी कार्यान्वयन के अनुरूप है (future के साथ संयोजन में)। मेरा मानना ​​है कि यह not conformant है। मैं इसे वीएस2013 के साथ पुन: पेश करने में सक्षम हूं, लेकिन इस मुद्दे को जीसीसी के साथ पुन: उत्पन्न करने में असमर्थ हूं।

दुर्घटना इसलिए है क्योंकि मुख्य धागा अन्य दो धागे पूर्ण होने से पहले बाहर निकलता है (और साफ करने लगता है)।

इसलिए दो वायदा पर एक साधारण देरी (sleep_for) या .get() या .wait() इसे आपके लिए ठीक करना चाहिए। तो संशोधित main जैसा दिख सकता है;

int main() 
{ 
    auto f1 = std::async(std::launch::async, print, "Hello from thread 1"); 
    auto f2 = std::async(std::launch::async, print, "Hello from thread 2"); 

    print(std::string("Hello from main"));  

    f1.get(); 
    f2.get(); 
} 

स्पष्ट प्रतीक्षा का पालन करें या समय "नींद" प्राप्त करें।

नोट्स अनुरूपता

पर Herb Sutter से एक प्रस्ताव इंतजार या future की साझा राज्य async से लौटे पर ब्लॉक बदलने के लिए नहीं था। यह एमएसवीसी में व्यवहार का कारण हो सकता है, इसे प्रस्ताव लागू करने के रूप में देखा जा सकता है। मुझे यकीन नहीं है कि प्रस्ताव का अंतिम परिणाम क्या था या इसका एकीकरण (या उसका हिस्सा) सी ++ 14 में था। कम से कम w.r.t. future को अवरुद्ध करना async से लौटाया गया ऐसा लगता है कि एमएसवीसी व्यवहार ने इसे विनिर्देशन में नहीं बनाया है।

यह ध्यान रखना दिलचस्प है कि §30.6 में शब्द।8/5 बदल गया;

सी ++ 11

एक अतुल्यकालिक वापसी उद्देश्य यह है कि साझा राज्य इस async कॉल द्वारा बनाई शेयरों जुड़े धागा जब तक ब्लॉक करेगा पर वेटिंग फ़ंक्शन की कॉल से, पूरा कर लिया है के रूप में यदि

में शामिल हो गए
सी ++ 14

एक अतुल्यकालिक वापसी वस्तु पर एक प्रतीक्षा फ़ंक्शन की कॉल कि टी के शेयरों के लिए

वह, राज्य, इस async कॉल द्वारा बनाई जुड़े धागा पूरा कर लिया है जब तक ब्लॉक करेगा के रूप में अगर में शामिल हो गए साझा वरना समय बाहर

मुझे यकीन है कि कैसे "समय के लिए बाहर" निर्दिष्ट किया जाएगा नहीं कर रहा हूँ मुझे लगता है कि यह कार्यान्वयन परिभाषित किया गया है।

+0

तो अपेक्षित व्यवहार क्या है? उन धागे के साथ चलने वाले धागे, शायद मुख्य धागे को समाप्त करने के बाद, टर्की के समान – Mikhail

+0

@ मिखाइल के साथ टर्की के समान चलना चाहिए। मुझे तुर्की समानता पसंद है, lol। मुझे लगता है कि यही कारण है कि प्रस्ताव शायद खारिज कर दिया गया था (कम से कम वह हिस्सा जहां धागे किसी भी प्रतीक्षा राज्य से अलग हो जाते हैं)। मुझे लगता है कि 'async' से ब्लॉक करने के लिए 'भविष्य' के लिए यह एक बेहतर विचार है। मुझे यह भी लगता है कि कभी-कभी 'भविष्य' के स्रोत के आसपास भ्रम होता है और चाहे वह अवरुद्ध हो या नहीं - शायद 'async_future' एक बेहतर विचार हो सकता है, लेकिन मुझे नहीं पता। मेरा मानना ​​है कि 'async' देर से जोड़ा गया था, इसलिए हो सकता है कि वे सभी सूक्ष्म मुद्दों को दूर नहीं कर पाएंगे। – Niall

1

std::async एक future देता है। यदि get या wait इसके destructor ब्लॉक नहीं बुलाया गया है:

तो निम्न बात कर रहे हैं के सभी रोक सकते: साझा राज्य एक फोन द्वारा बनाया गया था एसटीडी :: async, साझा राज्य अभी तक तैयार नहीं है , और यह साझा राज्य का अंतिम संदर्भ था।

विषय के विस्तृत उपचार के लिए std::futures from std::async aren't special! देखें।

+2

तो यह दुर्घटना की व्याख्या कैसे करता है? –

+2

यह कैसे समझाता है कि यह काम करता है अगर वह एक सेकंड के लिए सोता है? –

1

main के अंत में इन 2 लाइनों जोड़ें:

f1.wait(); 
f2.wait(); 

यह सुनिश्चित धागे से पहले main मौजूद खत्म कर देगा।

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