2009-05-13 6 views
9

मेरे पास 2 धागे हैं और एक साझा float वैश्विक है। एक धागा केवल चर को लिखता है जबकि दूसरा केवल इससे पढ़ता है, क्या मुझे इस चर के उपयोग को लॉक करने की आवश्यकता है? दूसरे शब्दों में:क्या मुझे एक लॉक की आवश्यकता है जब केवल एक ही थ्रेड किसी साझा चर को लिखता हो?

volatile float x; 

void reader_thread() { 
    while (1) { 
     // Grab mutex here? 
     float local_x = x; 
     // Release mutex? 
     do_stuff_with_value(local_x); 
    } 
} 

void writer_thread() { 
    while (1) { 
     float local_x = get_new_value_from_somewhere(); 
     // Grab mutex here? 
     x = local_x; 
     // Release mutex? 
    } 
} 

मेरा मुख्य चिंता यह है कि एक लोड या एक float की दुकान परमाणु नहीं किया जा रहा है, जैसे कि local_xreader_thread में एक फर्जी, आंशिक रूप से अद्यतन मूल्य होने समाप्त होता है।

  1. क्या यह एक वैध चिंता है?
  2. क्या म्यूटेक्स के बिना परमाणुता की गारंटी देने का कोई और तरीका है?
  3. साझा चर के काम के रूप में sig_atomic_t का उपयोग करेगा, मान लीजिए कि मेरे उद्देश्यों के लिए पर्याप्त बिट्स हैं?

प्रश्न में भाषा सी है pthreads का उपयोग कर सी है।

+0

आप म्यूटेक्स का उपयोग करने से क्यों बचना चाहते हैं? –

+0

पाठक धागा प्लगइन के रूप में गेम के हर फ्रेम को चलाएगा। हालांकि यह शायद समय से पहले अनुकूलन है, मैं किसी भी ओवरहेड से बचना चाहता था जो मैं कर सकता हूं। उस ने कहा, मैं जवाब से आश्वस्त हूं कि मुझे एक म्यूटेक्स का उपयोग करना चाहिए, और मुझे संदेह है कि ओवरहेड की मात्रा एक समस्या होगी। –

+0

सभी उत्तरों के लिए धन्यवाद। लगता है कि मुझे परमाणु होने के लिए विशेष रूप से पोर्टेबिलिटी के लिए पढ़ने/लिखने पर भरोसा नहीं करना चाहिए, इसलिए लॉकिंग जाने का तरीका प्रतीत होता है। –

उत्तर

12

विभिन्न आर्किटेक्चर के अलग-अलग नियम होते हैं, लेकिन सामान्य रूप से, स्मृति लोड और गठबंधन के स्टोर, int-आकार वाली वस्तुएं परमाणु हैं। छोटे और बड़े समस्याग्रस्त हो सकते हैं। तो यदि sizeof(float) == sizeof(int) आप सुरक्षित हो सकते हैं, लेकिन मैं अभी भी एक पोर्टेबल कार्यक्रम में इस पर निर्भर नहीं होगा।

इसके अलावा, volatile का व्यवहार विशेष रूप से अच्छी तरह से परिभाषित नहीं है ... विनिर्देश इसे स्मृति-मैप किए गए डिवाइस I/O तक पहुंच को अनुकूलित करने से रोकने के तरीके के रूप में उपयोग करता है, लेकिन किसी अन्य पर इसके व्यवहार के बारे में कुछ भी नहीं कहता है स्मृति का उपयोग करता है।

संक्षेप में, भले ही भार और दुकानों float x पर परमाणु कर रहे हैं, मैं स्पष्ट स्मृति बाधाओं volatile के आधार पर करने के बजाय में (हालांकि कैसे मंच और संकलक से भिन्न होता है) का प्रयोग करेंगे। भार और दुकानों परमाणु होने की गारंटी के बिना, आप ताले का उपयोग करने के लिए करेंगे, जो स्मृति बाधाओं को इंगित करता है।

+0

+1 टिप्पणी –

+0

"गठबंधन, int आकार के ऑब्जेक्ट्स की मेमोरी लोड और स्टोर्स परमाणु हैं" -> हाँ, लेकिन स्मृति प्रक्षेपण नहीं है। इसलिए x = 1 सेट करना अनिवार्य रूप से अन्य कोरों के लिए दृश्यमान है। आप ** एकाधिक सीपीयू के साथ इस विधि का उपयोग नहीं कर सकते हैं।यहां तक ​​कि एक लॉक भी आपकी मदद नहीं करता है, जब तक कि इसमें एक अंतर्निहित स्मृति बाधा न हो, क्योंकि लॉक आ सकता है और जब भी आप चाहते थे लिखते हैं * अभी भी * प्रचार नहीं किया गया है। –

+0

सीपीयू के बीच मेमोरी प्रचार आम तौर पर स्नातक पर होता है, लेकिन आप लिखते हैं कि ऑर्डरिंग की गारंटी नहीं है। हालांकि, मैंने अभी तक लॉकिंग लाइब्रेरी नहीं देखी है जिसमें अंतर्निहित स्मृति बाधाएं नहीं हैं। – ephemient

0

चूंकि यह स्मृति में एक शब्द है, आप बदल रहे हैं, आपको केवल अस्थिर घोषणा के साथ ठीक होना चाहिए।

मुझे नहीं लगता कि आप गारंटी देते हैं कि जब आप इसे पढ़ते हैं तो आपके पास नवीनतम मूल्य होगा, जब तक कि आप लॉक का उपयोग न करें।

+0

कृपया नीचे मोड को समझाएं। मैं कम से कम स्वीकृत उत्तर के समान कह रहा हूं। – justinhj

+0

मैं -1 को रद्द करने के लिए ऊपर जा रहा हूं क्योंकि मुझे नहीं लगता कि आपका उत्तर नकारात्मक है। मेरा अनुमान है कि जो भी डाउनवॉटेड ऐसा करता है, भले ही मैंने ताले लगाए हों, फिर भी यह गारंटी नहीं देगी कि मेरे पास नवीनतम मूल्य होगा (पाठक थ्रेड के बाद लेखक थ्रेड को नया मान प्राप्त हो सकता है, लेकिन इससे पहले कि इसे असाइन किया जाए साझा चर के लिए)। मेमोरी बाधाओं के लिए –

3

मैं इसे लॉक कर दूंगा। मुझे यकीन नहीं है कि float आपके पर्यावरण में कितना बड़ा है, लेकिन इसे एक ही निर्देश में पढ़ा/लिखा नहीं जा सकता है, इसलिए आपका पाठक आधे लिखित मूल्य को संभावित रूप से पढ़ सकता है। याद रखें कि volatile संचालन की परमाणुता के बारे में कुछ भी नहीं कहता है, यह केवल यह कहता है कि पढ़ना मेमोरी से एक रजिस्टर में कैश किए जाने के बजाय आएगा।

1

मुझे विश्वास है कि आपको एक म्यूटेक्स का उपयोग करना चाहिए। किसी दिन, आपका कोड उस सिस्टम पर चल सकता है जिसमें वास्तविक फ़्लोटिंग पॉइंट हार्डवेयर नहीं है और इसके बजाय इम्यूलेशन का उपयोग करता है, जिसके परिणामस्वरूप गैर-परमाणु फ्लोट चर होते हैं। उदाहरण के लिए, -oftoft-float here देखें।

मेरा जवाब बहुत उपयोगी नहीं था। gcc -msoft-float संभवतः केवल एक विशिष्ट मामला है जहां फ्लोट्स के लोड और स्टोर परमाणु नहीं हैं। धारा 24.4.7 के अनुसार

+0

मैंने उस संभावना के बारे में सोचा नहीं था - यह एक अच्छा मुद्दा है। –

4

।GNU सी पुस्तकालय प्रलेखन के 2:

अभ्यास में, आप मान सकते हैं कि int और अन्य int से अधिक समय नहीं पूर्णांक प्रकार परमाणु कर रहे हैं। आप यह भी मान सकते हैं कि सूचक प्रकार परमाणु हैं; यह बहुत सुविधाजनक है। इन दोनों धारणाओं को उन सभी मशीनों पर सत्य है जो जीएनयू सी लाइब्रेरी का समर्थन करता है और उन सभी पॉज़िक्स सिस्टम पर जिन्हें हम जानते हैं।

float तकनीकी रूप से, इन नियमों के अंतर्गत गिनती नहीं है, हालांकि अगर एक float अपने वास्तुकला पर एक int रूप में एक ही आकार है, अपने वैश्विक चर एक int, और फिर एक नाव के लिए परिवर्तित कर आप क्या कर सकता है हर बार जब आप इसे पढ़ते या लिखते हैं तो एक संघ के साथ।

साझा चर का उपयोग करने के लिए कार्रवाई का सबसे सुरक्षित तरीका म्यूटेक्स के कुछ रूपों का उपयोग करना है। चूंकि महत्वपूर्ण वर्ग बेहद छोटे हैं (एक परिवर्तनीय को पढ़ना/लिखना), आप निश्चित रूप से एक हल्के वजन वाले म्यूटेक्स जैसे स्पिन लॉक से बेहतर प्रदर्शन करने जा रहे हैं, क्योंकि एक भारी वजन वाले म्यूटेक्स के विपरीत जो सिस्टम बनाता है अपनी नौकरी करने के लिए कहते हैं।

+0

+1 अच्छा बिंदु; जब कोई विवाद नहीं होता है तो स्पिन लॉक अधिक जटिल लॉकिंग तंत्र की तुलना में बेहतर प्रदर्शन कर रहे हैं। – ephemient

3

असाइनमेंट कम से कम कुछ कंपाइलरों के लिए परमाणु नहीं है, और इस अर्थ में कि यह करने के लिए एक ही निर्देश लेता है। निम्नलिखित कोड विजुअल सी ++ 6.0 - एफ 1 और एफ 2 द्वारा उत्पन्न किया गया था प्रकार फ्लोट के हैं।

4:  f2 = f1; 
00401036 mov   eax,dword ptr [ebp-4] 
00401039 mov   dword ptr [ebp-8],eax 
+1

हाँ, आमतौर पर केवल "पंजीकरण करने के लिए स्मृति को स्थानांतरित करें" और "स्मृति में स्थानांतरित करें" निर्देश हैं, नहीं, "स्मृति में स्मृति को स्थानांतरित करें"। मुझे नहीं लगता कि ओपी के सवाल पर इसका कोई विशेष असर है, हालांकि; अगर यह reader_thread में था, "कॉपी करने के लिए x कॉपी करें" परमाणु है, और "मेरे स्टैक पर स्थानीय_एक्स पर प्रतिलिपि पंजीकृत करें" सुरक्षित है; लेखक_थ्रेड में स्थिति सममित है। reader_thread थोड़ा पुराना मूल्य देख सकता है, लेकिन यह एक असंगत मूल्य देखने से बहुत बेहतर है। – ephemient

0

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

हालांकि यह संभव है क्योंकि सी में एक फ्लोट की परिभाषा यह अनिवार्य नहीं है कि अंतर्निहित हार्डवेयर संग्रहण प्रोसेसर के शब्द आकार तक ही सीमित हो। आप मशीन कोड में संकलित हो सकते हैं, कहें, साइन, और मंथिसा दो अलग-अलग परिचालनों में लिखे गए हैं।

असली सवाल, मुझे लगता है, दो प्रश्न हैं: "यहां एक म्यूटक्स होने का नकारात्मक क्या है?" और "अगर मुझे कचरा पढ़ा जाता है तो क्या असर पड़ता है?"

शायद म्यूटेक्स की बजाय आपको एक जोर देना चाहिए जो निर्धारित करता है कि फ्लोट का संग्रहण आकार अंतर्निहित CPU के शब्द आकार के बराबर या बराबर है या नहीं।

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

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