कोर डेटा संरचनाओं में से कोई भी थ्रेड सुरक्षित नहीं है। रूबी के साथ जहाजों के बारे में मुझे पता है कि मानक पुस्तकालय (require 'thread'; q = Queue.new
) में कतार कार्यान्वयन है।
एमआरआई जीआईएल धागा सुरक्षा के मुद्दों से हमें बचाओ नहीं है। यह केवल यह सुनिश्चित करें कि दो धागे नहीं सटीक एक ही समय में एक ही समय पर रूबी कोड चला सकते हैं दो अलग अलग CPUs पर जैसे कि, बनाता है। थ्रेड अभी भी आपके कोड में किसी भी बिंदु पर रोका जा सकता है और फिर से शुरू किया जा सकता है। यदि आप @n = 0; 3.times { Thread.start { 100.times { @n += 1 } } }
जैसे कोड लिखते हैं उदा। एकाधिक धागे से एक साझा चर को म्यूट कर, बाद में साझा चर का मान निर्धारिती नहीं है। जीआईएल एक कोर सिस्टम की सिमुलेशन कम या ज्यादा है, यह सही समवर्ती कार्यक्रम लिखने के मौलिक मुद्दों को नहीं बदलता है।
भले ही एमआरआई नोड.जेएस की तरह एकल-थ्रेडेड हो, फिर भी आपको समरूपता के बारे में सोचना होगा। वृद्धिशील चर के साथ उदाहरण ठीक काम करेगा, लेकिन आप अभी भी दौड़ की स्थिति प्राप्त कर सकते हैं जहां चीजें गैर-निर्धारक क्रम में होती हैं और एक कॉलबैक क्लॉबर्स दूसरे का नतीजा होता है। सिंगल थ्रेडेड एसिंक्रोनस सिस्टम के बारे में तर्क करना आसान है, लेकिन वे समवर्ती मुद्दों से मुक्त नहीं हैं। बस एकाधिक उपयोगकर्ताओं के साथ एक एप्लिकेशन के बारे में सोचें: यदि दो उपयोगकर्ता एक ही समय में स्टैक ओवरफ़्लो पोस्ट पर एक ही समय में संपादित करते हैं, तो पोस्ट को संपादित करने में कुछ समय व्यतीत करें और फिर सहेजें को हिट करें, जिनके परिवर्तन बाद में किसी तीसरे उपयोगकर्ता द्वारा देखे जाएंगे उसी पोस्ट को पढ़ें?
रूबी में, अधिकांश अन्य समवर्ती रनटाइम्स के रूप में, एक से अधिक ऑपरेशन जो कुछ भी है, वह थ्रेड सुरक्षित नहीं है। @n += 1
धागा सुरक्षित नहीं है, क्योंकि यह कई संचालन है। @n = 1
धागा सुरक्षित है क्योंकि यह एक ऑपरेशन है (यह हुड के नीचे बहुत सारे ऑपरेशन है, और अगर मैं यह वर्णन करने की कोशिश करता हूं कि यह "धागा सुरक्षित" क्यों है, तो अंत में मुझे असंगत परिणाम नहीं मिलेगा कार्य)। @n ||= 1
, नहीं है और कोई अन्य शॉर्टेंड ऑपरेशन + असाइनमेंट या तो नहीं है। एक गलती मैंने कई बार बनाई है return unless @started; @started = true
लिख रहा है, जो बिल्कुल थ्रेड सुरक्षित नहीं है।
मुझे रूबी के लिए थ्रेड सुरक्षित और गैर थ्रेड सुरक्षित कथन की किसी भी आधिकारिक सूची के बारे में पता नहीं है, लेकिन अंगूठे का एक साधारण नियम है: यदि कोई अभिव्यक्ति केवल एक (साइड-इफेक्ट फ्री) ऑपरेशन करता है तो यह शायद सुरक्षित धागा।उदाहरण के लिए: a + b
ठीक है, a = b
भी ठीक है, और ठीक है, यदि विधि foo
साइड-इफेक्ट मुक्त है (चूंकि रूबी में कुछ भी एक विधि कॉल है, यहां तक कि कई मामलों में असाइनमेंट भी है, यह इसके लिए जाता है अन्य उदाहरण भी)। इस संदर्भ में दुष्प्रभाव का मतलब है कि चीजें जो राज्य को बदलती हैं। def foo(x); @x = x; end
साइड-इफेक्ट मुक्त नहीं है।
रूबी में थ्रेड सुरक्षित कोड लिखने की सबसे कठिन चीजों में से एक यह है कि सरणी, हैश और स्ट्रिंग समेत सभी मूल डेटा संरचनाएं उत्परिवर्तनीय हैं। गलती से अपने राज्य का एक टुकड़ा रिसाव करना बहुत आसान है, और जब वह टुकड़ा उत्परिवर्तनीय चीजें वास्तव में खराब हो सकता है। निम्नलिखित कोड पर विचार करें:
class Thing
attr_reader :stuff
def initialize(initial_stuff)
@stuff = initial_stuff
@state_lock = Mutex.new
end
def add(item)
@state_lock.synchronize do
@stuff << item
end
end
end
इस वर्ग का एक उदाहरण धागे के बीच साझा किया जा सकता है और वे सुरक्षित रूप से इसे करने के लिए चीजों को जोड़ सकते हैं, लेकिन वहाँ एक संगामिति बग (यह केवल एक नहीं है) है: वस्तु की आंतरिक स्थिति stuff
एक्सेसर के माध्यम से लीक। Encapsulation परिप्रेक्ष्य से समस्याग्रस्त होने के अलावा, यह concurrency कीड़े के एक कैन खोलता है। हो सकता है कि कोई उस सरणी को ले लेता है और इसे कहीं और पास करता है, और उस कोड को बदले में लगता है कि अब यह उस सरणी का मालिक है और जो कुछ भी इसके साथ चाहता है वह कर सकता है।
एक और क्लासिक रूबी उदाहरण यह है:
STANDARD_OPTIONS = {:color => 'red', :count => 10}
def find_stuff
@some_service.load_things('stuff', STANDARD_OPTIONS)
end
find_stuff
काम करता है पहली बार यह प्रयोग किया जाता है ठीक है, लेकिन कुछ दूसरी बार देता है। क्यूं कर? load_things
विधि यह सोचने के लिए होती है कि यह विकल्प हैश पास हो गया है, और color = options.delete(:color)
करता है। अब STANDARD_OPTIONS
निरंतर एक ही मूल्य नहीं है। कॉन्स्टेंट केवल वे संदर्भ में स्थिर होते हैं, वे संदर्भित डेटा संरचनाओं की स्थिरता की गारंटी नहीं देते हैं। बस सोचें कि क्या होगा यदि यह कोड समवर्ती रूप से चलाया गया था।
आप परिवर्तनशील राज्य साझा से बचने है (एक से अधिक थ्रेड द्वारा पहुँचा वस्तुओं में जैसे उदाहरण चर, हैश और सरणियों से अधिक थ्रेड द्वारा पहुँचा तरह डेटा संरचनाओं) धागा सुरक्षा इतनी मेहनत नहीं है। अपने आवेदन के उन हिस्सों को कम करने की कोशिश करें जिन्हें समवर्ती रूप से एक्सेस किया गया हो, और वहां अपने प्रयासों पर ध्यान केंद्रित करें। आईआईआरसी, रेल अनुप्रयोग में, प्रत्येक अनुरोध के लिए एक नया नियंत्रक ऑब्जेक्ट बनाया जाता है, इसलिए यह केवल एक थ्रेड द्वारा उपयोग किया जा रहा है, और यह उस नियंत्रक से आपके द्वारा बनाई गई किसी भी मॉडल ऑब्जेक्ट के लिए जाता है। हालांकि, रेल वैश्विक चर के उपयोग को भी प्रोत्साहित करते हैं (User.find(...)
वैश्विक चर User
का उपयोग करता है, आप इसे केवल एक वर्ग के रूप में सोच सकते हैं, और यह एक वर्ग है, लेकिन यह वैश्विक चर के लिए नामस्थान भी है), इनमें से कुछ सुरक्षित हैं क्योंकि वे केवल पढ़े जाते हैं, लेकिन कभी-कभी आप इन वैश्विक चरों में चीजें सहेजते हैं क्योंकि यह सुविधाजनक है। जब आप वैश्विक स्तर पर पहुंच योग्य कुछ भी उपयोग करते हैं तो बहुत सावधान रहें।
रेल कुछ समय के लिए थ्रेडेड वातावरण में रेल चलाने के लिए संभव है, इसलिए रेल विशेषज्ञ होने के बावजूद मैं अब तक कहूंगा कि रेल की बात होने पर आपको थ्रेड सुरक्षा के बारे में चिंता करने की ज़रूरत नहीं है अपने आप। आप अभी भी रेल अनुप्रयोगों को बना सकते हैं जो ऊपर बताई गई कुछ चीजों को करके थ्रेड सुरक्षित नहीं हैं। जब यह अन्य रत्न आता है तो मान लें कि वे धागे सुरक्षित नहीं हैं जब तक वे कहते हैं कि वे हैं, और यदि वे कहते हैं कि वे मानते हैं कि वे नहीं हैं, और उनके कोड को देखते हैं (लेकिन सिर्फ इसलिए कि आप देखते हैं कि वे @n ||= 1
जैसी चीजें करते हैं इसका मतलब यह नहीं है कि वे धागे सुरक्षित नहीं हैं, यह सही संदर्भ में करने के लिए एक पूरी तरह से वैध बात है - आपको वैश्विक चर में उत्परिवर्तनीय स्थिति जैसी चीजों की तलाश करनी चाहिए, यह कैसे अपने तरीकों से उत्परिवर्तनीय वस्तुओं को पारित करता है, और विशेष रूप से यह कैसे संभालता है विकल्प हैश)।
अंत में, थ्रेड असुरक्षित होने के कारण एक संक्रमणीय संपत्ति है। कुछ भी जो कुछ ऐसा उपयोग करता है जो थ्रेड सुरक्षित नहीं है, वह स्वयं थ्रेड सुरक्षित नहीं है।
आप सुनिश्चित करें कि सभी कोड और जो कुछ कर रहे हैं रत्न थ्रेडसेफ होना चाहिए? रिलीज नोट्स का कहना है कि रेल स्वयं ही थ्रेडसेफ होंगे, न कि इसके साथ उपयोग की जाने वाली हर चीज – enthrops
होनी चाहिए बहु-थ्रेडेड टेस्ट सबसे खराब थ्रेडसेफ जोखिम होगा। जब आपको अपने टेस्ट केस के आस-पास एक पर्यावरण चर के मान को बदलना होता है, तो आप तुरन्त थ्रेडसेफ नहीं होते हैं। आप इसके आसपास कैसे काम करेंगे? और हाँ, सभी रत्नों को थ्रेडसेफ होना चाहिए। –