2015-12-20 22 views
5

में साझा वैरिएबल इसलिए मैंने पिछले सेमेस्टर में ओएस क्लास लिया और हमारे पास एक समवर्ती/थ्रेडिंग प्रोजेक्ट था। यह एक हवाई अड्डे का सिम था जो विमानों से उतरा था/उन्हें हवा में उड़ने वाली दिशा में ले जाया गया था। हमें जावा में ऐसा करना था। तो अब यह खत्म हो गया है और मैं ऊब गया हूं, मैं इसे सी ++ 11 में करने की कोशिश कर रहा हूं। जावा में मैंने मुख्य रूप से हवा (0 - 360) के लिए सिंक्रनाइज़ वैरिएबल का उपयोग किया और इसे इस्तेमाल किए गए 3 धागे तक पारित कर दिया। मेरा सवाल है: क्या आप इसे सी ++ 11 में कर सकते हैं? यह एक मूल पाठक/लेखक है, एक थ्रेड हवा लिखता है/अपडेट करता है, दूसरा 2 (टेकऑफ/भूमि) पढ़ता है।सी ++ 11

मुझे यह मेरी "threads.cpp" कार्यान्वयन फ़ाइल में वैश्विक पवन चर रखने के द्वारा काम कर रहा है। लेकिन क्या एक वैरिएबल को जितने चाहें उतने धागे को पास करने का कोई तरीका है और वे सभी इसके साथ रहते हैं? या क्या यह वास्तव में मेरे लिए ग्लोबल वैरिएबल का उपयोग करना और कुछ भी पास नहीं करना बेहतर है? (क्यों/क्यों नहीं?) मैं std::ref() पर देख रहा था लेकिन यह काम नहीं करता था।

संपादित करें: मैं पहले से ही mutex और lock_guard का उपयोग कर रहा हूं। मैं बस यह पता लगाने की कोशिश कर रहा हूं कि सभी थ्रेडों में एक चर को अद्यतित कैसे करें और अद्यतित रखें। अभी यह केवल लेखन धागे में अपडेट होता है।

उत्तर

5

साझा डेटा तक पहुंच को सिंक्रनाइज़ करने के लिए आप std::lock_guard के साथ std::mutex का उपयोग कर सकते हैं। या यदि साझा डेटा एक पूर्णांक में फिट बैठता है, तो आप लॉकिंग के बिना std::atomic<int> का उपयोग कर सकते हैं।

यदि आप वैश्विक चर से बचना चाहते हैं, तो साझा किए गए राज्य के पते को जब आप लॉन्च करते हैं तो थ्रेड फ़ंक्शंस को पास करें। उदाहरण के लिए:

void thread_entry1(std::atomic<int>* val) {} 
void thread_entry2(std::atomic<int>* val) {} 

std::atomic<int> shared_value; 
std::thread t1(thread_entry1, &shared_value); 
std::thread t2(thread_entry2, &shared_value); 
+0

हाँ, यह वही है जो मैं करने की कोशिश कर रहा था! ऐसा लगता है कि यह एक दर्द का अधिक है, फिर वैश्विक वैरिएबल का उपयोग करते हुए। क्या इस तरह से ऐसा करने के लिए कोई +/- है? – lciamp

+3

खैर, ज्यादातर लोग वैश्विक चर को ज्यादातर समय खराब अभ्यास मानते हैं। कम से कम परीक्षण करना मुश्किल बनाता है। –

1

आप एक std::shared_ptr के माध्यम से कहते हैं बनाने के लिए, हवा वस्तु, new साथ ढेर पर चाहते हो सकता है। इस सूचक को सभी इच्छुक धागे में पास करें और इसे बदलने के लिए std::mutex और std::lock_guard का उपयोग करें।

+0

धन्यवाद। मुझे shared_ptr को देखना होगा।मैं सिर्फ सी ++ 98 से 11 में परिवर्तन कर रहा हूं, एक मजेदार शीतकालीन तोड़ होना चाहिए! – lciamp

+1

आप जावा से सी ++ में भी बदलाव कर रहे हैं और यह एक पिवट पॉइंट है जिसे आपको अपने सिर को पाने की आवश्यकता है। जावा ऑब्जेक्ट्स में आपके लिए प्रबंधित ढेर और मेमोरी पर स्वचालित रूप से बनाया जाता है। सी ++ में आपको इस जिम्मेदारी को स्वयं लेना होगा। लेकिन कुछ महान सी ++ 11 (और सी ++ 14!) मानक लाइब्रेरी हेल्पर्स हैं जिन्हें आपको इस यात्रा को जितना संभव हो उतना मीठा बनाने के लिए पकड़ने की आवश्यकता है .. सी ++ भूमि में आपका स्वागत है सर्दी ब्रेक! :)) –

2

std::mutex और std::lock_guard का उपयोग करते हुए एक जावा सिंक्रनाइज़ वैरिएबल करता है (केवल जावा में यह जानने के बिना गुप्त रूप से होता है, सी ++ में आप इसे स्पष्ट रूप से करते हैं)।

हालांकि, एक निर्माता (हवा की केवल एक दिशा है) और अन्यथा उपभोक्ता, यह एक उदाहरण के लिए लिखने के लिए पर्याप्त है std::atomic<int> आराम से आदेश के साथ परिवर्तनीय, और प्रत्येक उपभोक्ता से उस चर से पढ़ने के लिए, फिर से आराम से आदेश के साथ। जब तक आपको आवश्यकता न हो कि सभी विमानों का वैश्विक दृष्टिकोण सुसंगत रहे (लेकिन फिर आपको लॉकस्टेप सिमुलेशन चलाया जाना चाहिए, जो थ्रेडिंग को असंवेदनशील बनाता है), सिंक्रनाइज़ेशन की कोई आवश्यकता नहीं है, आपको केवल यह सुनिश्चित करना होगा कि कोई भी मूल्य हवाई जहाज किसी भी समय पढ़ता है अंततः सही है और कोई गड़बड़ मध्यवर्ती परिणाम नहीं हो सकता है। दूसरे शब्दों में, आपको एक परमाणु अद्यतन की आवश्यकता है।
आराम से मेमोरी ऑर्डरिंग भी पर्याप्त है, क्योंकि यदि आप जो भी पढ़ते हैं वह एक मान है, तो आपको किसी भी होने वाली गारंटी की आवश्यकता नहीं होती है।

एक परमाणु अद्यतन (या बल्कि, परमाणु लेखन) कम से कम, अधिक नहीं, तो कम से कम परिमाण का क्रम है। परमाणु पढ़ने के साथ परमाणु पढ़ता है और लिखता है वास्तव में कई सामान्य (मुख्य) मुख्यधारा के आर्किटेक्चर पर सामान्य सामान्य पढ़ता है और लिखता है।

परिवर्तनीय वैश्विक नहीं होना चाहिए, आप इसे मुख्य थ्रेड के सिमुलेशन लूप के दायरे में भी रख सकते हैं और धागे को संदर्भ (या सूचक) पास कर सकते हैं।

+0

हुह। म्यूटेक्स/लॉक_गार्ड की तुलना में मेरी समस्या के लिए परमाणु की तरह लगता है। मैं क्या कर रहा था, क्योंकि मैं पहले से लिखा गया जावा कोड देख रहा था, संदर्भ के बजाय मूल्य से गुजर रहा था। मुझे जांच करनी चाहिए रनवे के लिए हवा और म्यूटेक्स/लॉक_गार्ड के लिए परमाणु का उपयोग करें। सहायता के लिए धन्यवाद! – lciamp

+0

रनवे के लिए म्यूटेक्स निश्चित रूप से समझ में आता है क्योंकि एक ही समय में केवल एक विमान रनवे पर हो सकता है (बिना चीजें खराब हो रही हैं)। केवल वर्तमान हवा दिशा को नमूना देने के लिए वास्तव में म्यूटेक्स की आवश्यकता नहीं है। – Damon

+0

एक std :: atomic का उपयोग निश्चित रूप से काम करता है, लेकिन यह समयपूर्व अनुकूलन है। चूंकि कई चर (रनवे, हवा, ...) पूरे राज्य की रक्षा के लिए एक म्यूटेक्स हैं, ध्यान में रखना पहली बात है। – galinette