एक दौड़ की स्थिति क्या है?


980

जब मल्टीथ्रेडेड एप्लिकेशन लिखते हैं, तो अनुभवी सबसे आम समस्याओं में से एक दौड़ की स्थिति है।

समुदाय के लिए मेरे प्रश्न हैं:

दौड़ की स्थिति क्या है?
आप उनका पता कैसे लगाते हैं?
आप उन्हें कैसे संभालेंगे?
अंत में, आप उन्हें होने से कैसे रोकेंगे?


3
लिनक्स HOWTO के लिए सुरक्षित प्रोग्रामिंग में एक महान अध्याय है जो बताता है कि वे क्या हैं, और उनसे कैसे बचें।
क्रेग एच

4
मैं यह उल्लेख करना चाहूंगा कि - भाषा को निर्दिष्ट किए बिना - इस प्रश्न के अधिकांश भागों का ठीक से उत्तर नहीं दिया जा सकता है, क्योंकि विभिन्न भाषाओं में, परिभाषा, परिणाम और उन्हें रोकने के उपकरण भिन्न हो सकते हैं।
माइकएमबी

@MikeMB। सहमति,, जैसे कि यह रेस कैचर द्वारा किया जाता है जब बाइट कोड निष्पादन का विश्लेषण करने के सिवाय (इस सूत्र को देखने stackoverflow.com/a/29361427/1363844 ) हम उन सभी लगभग 62 भाषाओं कि बाइट कोड को संकलन (देखें पता कर सकते हैं en.wikipedia.org / wiki / List_of_JVM_languages )
बेन

जवाबों:


1236

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

समस्याएँ अक्सर तब होती हैं जब एक थ्रेड "चेक-एक्ट-एक्ट" करता है (उदाहरण के लिए "चेक" यदि मान X है, तो "एक्ट" कुछ ऐसा करने के लिए जो मूल्य X पर निर्भर करता है) और दूसरा थ्रेड वैल्यू में कुछ करता है "चेक" और "अधिनियम" के बीच। उदाहरण के लिए:

if (x == 5) // The "Check"
{
   y = x * 2; // The "Act"

   // If another thread changed x in between "if (x == 5)" and "y = x * 2" above,
   // y will not be equal to 10.
}

बिंदु जा रहा है, y 10 हो सकता है, या यह कुछ भी हो सकता है, इस पर निर्भर करता है कि चेक और अधिनियम के बीच एक और धागा एक्स बदल गया या नहीं। आपके पास जानने का कोई वास्तविक तरीका नहीं है।

दौड़ की स्थितियों को होने से रोकने के लिए, आप आमतौर पर साझा किए गए डेटा के चारों ओर एक लॉक लगाते हैं ताकि यह सुनिश्चित किया जा सके कि एक समय में केवल एक धागा डेटा तक पहुंच सकता है। इसका मतलब कुछ इस तरह होगा:

// Obtain lock for x
if (x == 5)
{
   y = x * 2; // Now, nothing can change x until the lock is released. 
              // Therefore y = 10
}
// release lock for x

121
ताला का सामना करने पर दूसरा धागा क्या करता है? क्या यह इंतजार करता है? त्रुटि?
ब्रायन ओर्टिज़

173
हां, दूसरे धागे को तब तक इंतजार करना होगा जब तक कि आगे बढ़ने से पहले ताला जारी न हो जाए। यह बहुत महत्वपूर्ण बनाता है कि लॉक को थ्रेड द्वारा जारी किया जाता है जब इसके साथ समाप्त होता है। यदि यह इसे कभी जारी नहीं करता है, तो दूसरा धागा अनिश्चित काल तक इंतजार करेगा।
लेहेन

2
@ मैं एक मल्टीथ्रेडेड सिस्टम में हमेशा ऐसे समय होता है जब संसाधनों को साझा करने की आवश्यकता होती है। यह कहना कि वैकल्पिक नहीं है, केवल एक दृष्टिकोण बुरा है, उत्पादक नहीं है। मैं हमेशा सुधार करने के तरीकों की तलाश कर रहा हूं और अगर कोई विकल्प है तो मैं ख़ुशी से इसे अनुसंधान करूंगा और समर्थक और विपक्ष का वजन करूंगा।
डेस्परटेर

2
@Despertar ... यह भी, जरूरी नहीं कि संसाधन हमेशा एक थ्रेडेड थ्रेडेड सिस्टम में साझा किए जाने की आवश्यकता होगी। उदाहरण के लिए आपके पास एक सरणी हो सकती है जहां प्रत्येक तत्व को प्रसंस्करण की आवश्यकता होती है। आप संभवतः विभाजन को विभाजित कर सकते हैं और प्रत्येक विभाजन के लिए एक धागा हो सकते हैं और धागे एक दूसरे से स्वतंत्र रूप से अपना काम कर सकते हैं।
इयान वारबटन

12
दौड़ होने के लिए यह पर्याप्त है कि एक एकल थ्रेड साझा किए गए डेटा को बदलने का प्रयास करता है जबकि बाकी थ्रेड्स या तो इसे पढ़ सकते हैं या इसे बदल सकते हैं।
SomeWittyUsername

213

एक "दौड़ की स्थिति" तब मौजूद होती है जब एक साझा संसाधन तक पहुंचने वाले मल्टीथ्रेडेड (या अन्यथा समानांतर) कोड इस तरह से ऐसा कर सकता है जिससे अप्रत्याशित परिणाम हो सकते हैं।

इस उदाहरण को लें:

for ( int i = 0; i < 10000000; i++ )
{
   x = x + 1; 
}

यदि आपके पास 5 धागे हैं जो एक साथ इस कोड को निष्पादित करते हैं, तो x WULULD का मूल्य 50,000,000 तक नहीं है। यह वास्तव में प्रत्येक रन के साथ अलग-अलग होगा।

ऐसा इसलिए है क्योंकि प्रत्येक थ्रेड के लिए x का मान बढ़ाने के लिए, उन्हें निम्नलिखित कार्य करने होंगे: (सरलीकृत, स्पष्ट रूप से)

X का मान पुनः प्राप्त करें
इस मान में 1 जोड़ें
इस मान को x में संग्रहीत करें

कोई भी धागा किसी भी समय इस प्रक्रिया में किसी भी चरण में हो सकता है, और साझा संसाधन शामिल होने पर वे एक दूसरे पर कदम रख सकते हैं। X की स्थिति को दूसरे थ्रेड द्वारा उस समय के दौरान बदला जा सकता है जब x पढ़ा जा रहा हो और जब वह वापस लिखा जाए।

मान लें कि एक थ्रेड x का मान प्राप्त करता है, लेकिन इसे अभी तक संग्रहीत नहीं किया है। एक और धागा भी x का समान मान निकाल सकता है (क्योंकि किसी भी धागे ने इसे अभी तक नहीं बदला है) और फिर वे दोनों एक ही मूल्य (x + 1) को वापस x में संग्रहीत कर रहे होंगे !

उदाहरण:

थ्रेड 1: x को पढ़ता है, मान 7 है
थ्रेड 1: 1 से x जोड़ें, मान अब 8 है
थ्रेड 2: x को पढ़ता है, मान 7 है
थ्रेड 1: स्टोर एक्स में 8
थ्रेड 2: 1 से x जोड़ता है, मान अब 8 है
धागा 2: स्टोर एक्स में 8

साझा संसाधन तक पहुँचने वाले कोड से पहले कुछ प्रकार के लॉकिंग तंत्र को नियोजित करके दौड़ की स्थितियों से बचा जा सकता है :

for ( int i = 0; i < 10000000; i++ )
{
   //lock x
   x = x + 1; 
   //unlock x
}

यहां, हर बार 50,000,000 के रूप में उत्तर निकलता है।

लॉकिंग के बारे में अधिक जानने के लिए: म्यूटेक्स, सेमाफोर, महत्वपूर्ण अनुभाग, साझा संसाधन।


एक कार्यक्रम के उदाहरण के लिए jakob.engbloms.se/archives/65 देखें कि कैसे ऐसी चीजें खराब होती हैं, यह परीक्षण करने के लिए ... यह वास्तव में आपके द्वारा चलाए जा रहे मशीन के मेमोरी मॉडल पर निर्भर करता है।
जकोबोन्ग्लोम 2

1
अगर इसे 10 मिलियन पर रोकना है तो यह 50 मिलियन तक कैसे पहुंच सकता है?

9
@nocomprende: एक समय में एक ही कोड को निष्पादित करने वाले 5 थ्रेड्स, जैसा कि सीधे स्निपेट के नीचे वर्णित है ...
जॉन स्कीट

4
@JonSkeet आप सही हैं, मैंने i और x को भ्रमित किया है। धन्यवाद।

सिंगलटन पैटर्न को लागू करने में डबल चेक लॉकिंग दौड़ की स्थिति को रोकने का एक उदाहरण है।
Bharat Dodeja

150

रेस कंडीशन क्या है?

आप शाम 5 बजे किसी फिल्म में जाने की योजना बना रहे हैं। आप शाम 4 बजे टिकटों की उपलब्धता के बारे में पूछताछ करते हैं। प्रतिनिधि का कहना है कि वे उपलब्ध हैं। आप आराम करें और शो से 5 मिनट पहले टिकट खिड़की पर पहुँचें। मुझे यकीन है कि आप अनुमान लगा सकते हैं कि क्या होता है: यह एक पूर्ण घर है। यहाँ समस्या जाँच और कार्रवाई के बीच की अवधि में थी। आपने 4 से पूछताछ की और 5. पर काम किया। इस बीच, किसी और ने टिकट हड़प लिया। यह एक दौड़ की स्थिति है - विशेष रूप से दौड़ स्थितियों का एक "चेक-एक्ट-एक्ट" परिदृश्य।

आप उनका पता कैसे लगाते हैं?

धार्मिक कोड की समीक्षा, बहु-पिरोया इकाई परीक्षण। कोई शॉर्टकट नहीं है। इस पर कुछ एक्लिप्स प्लगइन उभर रहे हैं, लेकिन अभी तक कुछ भी स्थिर नहीं है।

आप उन्हें कैसे संभालते हैं और रोकते हैं?

सबसे अच्छी बात यह होगी कि साइड-इफ़ेक्ट फ़्री और स्टेटलेस फ़ंक्शंस बनाएं, जितना संभव हो सके इम्यूलेट्स का उपयोग करें। लेकिन ऐसा हमेशा संभव नहीं है। इसलिए java.util.concurrent.atomic, समवर्ती डेटा संरचनाओं, उचित सिंक्रनाइज़ेशन और अभिनेता आधारित समरूपता का उपयोग करने में मदद मिलेगी।

सुगमता के लिए सबसे अच्छा संसाधन JCIP है। आप ऊपर दिए गए स्पष्टीकरण पर कुछ और विवरण भी प्राप्त कर सकते हैं


कोड समीक्षा और इकाई परीक्षण आपके कानों के बीच प्रवाह को मॉडलिंग करने और साझा स्मृति का कम उपयोग करने के लिए माध्यमिक हैं।
एक्यूमेनस

2
मैंने दौड़ की स्थिति के वास्तविक विश्व उदाहरण की सराहना की
टॉम ओ।

11
जवाब की तरह अंगूठे । समाधान है: आप म्यूटेक्स (आपसी अपवाद, सी ++) के साथ टिकटों को 4-5 के बीच लॉक करते हैं। वास्तविक दुनिया में इसे टिकट आरक्षण कहा जाता है :)
वोल्ट

1
यदि आप जावा-केवल बिट्स गिराते हैं, तो एक सभ्य जवाब होगा (सवाल जावा के बारे में नहीं है, बल्कि सामान्य रूप से दौड़ की स्थिति है)
कोरी गोल्डबर्ग

नहीं, यह एक दौड़ की स्थिति नहीं है। एक "व्यवसाय" के नजरिए से आपने अभी बहुत लंबा इंतजार किया है। जाहिर है कि बैकऑर्डर एक समाधान नहीं है। एक
स्केलर की

65

दौड़ की स्थिति और डेटा दौड़ के बीच एक महत्वपूर्ण तकनीकी अंतर है। अधिकांश उत्तर यह धारणा बनाते प्रतीत होते हैं कि ये शब्द समतुल्य हैं, लेकिन वे नहीं हैं।

एक डेटा रेस तब होती है जब 2 निर्देश एक ही मेमोरी लोकेशन को एक्सेस करते हैं, इनमें से कम से कम एक एक्सेस एक राइट होता है और इन एक्सेस के बीच ऑर्डर करने से पहले ऐसा कुछ नहीं होता है । अब ऑर्डर करने से पहले जो होता है वह बहुत बहस का विषय होता है, लेकिन सामान्य लॉक-लॉक जोड़े में एक ही लॉक वैरिएबल पर और एक ही कंडीशन के वैरिएबल पर वेट-सिग्नल जोड़े एक ऑर्डर से पहले के ऑर्डर को प्रेरित करते हैं।

एक दौड़ की स्थिति एक शब्दार्थ त्रुटि है। यह एक दोष है कि समय या घटनाओं के आदेश में होता है कि गलत कार्यक्रम के लिए सुराग व्यवहार

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

अब जब हमने शब्दावली को समाप्त कर दिया है, तो हम मूल प्रश्न का उत्तर देने का प्रयास करें।

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

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

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


अंतर दौड़ की स्थिति को समझने के लिए महत्वपूर्ण है। धन्यवाद!
प्रोग्रामकैप

37

एक प्रकार की विहित परिभाषा " जब दो धागे एक ही समय में स्मृति में एक ही स्थान तक पहुंचते हैं, और कम से कम एक एक्सेस एक लेखन होता है ।" इस स्थिति में "रीडर" थ्रेड को पुराना मान या नया मान मिल सकता है, जिसके आधार पर "रेस जीतता है।" यह हमेशा एक बग नहीं है - वास्तव में, कुछ वास्तव में बालों वाले निम्न-स्तर के एल्गोरिदम इस उद्देश्य से करते हैं - लेकिन इसे आमतौर पर टाला जाना चाहिए। @Steve Gury एक अच्छा उदाहरण देता है जब यह एक समस्या हो सकती है।


3
क्या आप इस बात का उदाहरण दे सकते हैं कि कैसे दौड़ की स्थिति उपयोगी हो सकती है? Googling ने मदद नहीं की।
एलेक्स वी।

3
@ एलेक्स वी। इस बिंदु पर, मुझे नहीं पता कि मैं किस बारे में बात कर रहा था। मुझे लगता है कि यह लॉक-फ्री प्रोग्रामिंग के लिए एक संदर्भ हो सकता है, लेकिन यह कहना वास्तव में सटीक नहीं है कि दौड़ की स्थिति पर निर्भर करता है, प्रति से।
क्रिस कॉनवे

33

एक दौड़ की स्थिति एक प्रकार की बग है, जो केवल कुछ अस्थायी स्थितियों के साथ होती है।

उदाहरण: कल्पना कीजिए कि आपके दो धागे हैं, ए और बी।

थ्रेड ए में:

if( object.a != 0 )
    object.avg = total / object.a

थ्रेड बी में:

object.a = 0

यदि थ्रेड ए की जांच के बाद ही यह बताया जाता है कि ऑब्जेक्ट अशक्त नहीं है, बी करेगा a = 0, और जब थ्रेड ए प्रोसेसर को प्राप्त करेगा, तो यह "शून्य से विभाजित" करेगा।

यह बग केवल तब होता है जब थ्रेड ए केवल स्टेटमेंट के बाद प्रीमेप्टेड होता है, यह बहुत दुर्लभ है, लेकिन यह हो सकता है।


21

रेस की स्थिति न केवल सॉफ्टवेयर से संबंधित है, बल्कि हार्डवेयर से भी संबंधित है। दरअसल यह शब्द शुरू में हार्डवेयर उद्योग द्वारा गढ़ा गया था।

विकिपीडिया के अनुसार :

यह शब्द दो संकेतों के विचार से उत्पन्न होता है जो पहले आउटपुट को प्रभावित करने के लिए एक दूसरे को रेसिंग करते हैं

एक तर्क सर्किट में दौड़ की स्थिति:

यहां छवि विवरण दर्ज करें

सॉफ्टवेयर उद्योग ने बिना संशोधन के इस शब्द को लिया, जिससे इसे समझना थोड़ा मुश्किल हो जाता है।

आपको सॉफ़्टवेयर की दुनिया में इसे बदलने के लिए कुछ प्रतिस्थापन करने की आवश्यकता है:

  • "दो संकेत" => "दो सूत्र" / "दो प्रक्रियाएं"
  • "प्रभावित आउटपुट" => "कुछ साझा स्थिति को प्रभावित करें"

इसलिए सॉफ्टवेयर उद्योग में दौड़ की स्थिति का अर्थ है "दो धागे" / "दो प्रक्रियाएं" एक दूसरे को "कुछ साझा स्थिति को प्रभावित करने के लिए" रेसिंग, और साझा राज्य का अंतिम परिणाम कुछ सूक्ष्म समय अंतर पर निर्भर करेगा, जो कुछ विशिष्ट के कारण हो सकता है थ्रेड / प्रोसेस लॉन्चिंग ऑर्डर, थ्रेड / प्रोसेस शेड्यूलिंग आदि।


20

एक दौड़ की स्थिति समवर्ती प्रोग्रामिंग पर एक स्थिति है जहां दो समवर्ती धागे या प्रक्रियाएं संसाधन के लिए प्रतिस्पर्धा करती हैं और परिणामी अंतिम स्थिति इस बात पर निर्भर करती है कि संसाधन पहले कौन प्राप्त करता है।


सिर्फ शानदार विवरण
gokareless

अंतिम स्थिति क्या है?
रोमन एलेक्जेंड्रोविच

1
@ रोमान अलेक्सांद्रोविच कार्यक्रम की अंतिम स्थिति। राज्य जैसे चरों के मूल्यों का जिक्र करते हैं, इत्यादि, लेहेन का उत्कृष्ट उत्तर देखें। उनके उदाहरण में "राज्य" 'x' और 'y' के अंतिम मूल्यों को संदर्भित करेगा।
AMTerp

19

बहु-थ्रेडेड एप्लिकेशन या मल्टी-प्रोसेस सिस्टम में रेस की स्थिति होती है। एक दौड़ की स्थिति, इसके सबसे मूल में, कुछ भी है जो यह धारणा बनाता है कि एक ही धागे या प्रक्रिया में दो चीजें एक विशेष क्रम में नहीं होंगी, यह सुनिश्चित करने के लिए कदम उठाए बिना कि वे करते हैं। यह आमतौर पर तब होता है जब दो धागे एक वर्ग के सदस्य चर की स्थापना और जाँच करके संदेश भेज रहे हैं जो दोनों का उपयोग कर सकते हैं। लगभग हमेशा एक दौड़ की स्थिति होती है जब एक थ्रेड किसी कार्य को पूरा करने के लिए एक और थ्रेड समय देने के लिए नींद को बुलाता है (जब तक कि नींद लूप में न हो, कुछ जाँच तंत्र के साथ)।

दौड़ की स्थिति को रोकने के लिए उपकरण भाषा और OS पर निर्भर हैं, लेकिन कुछ कॉमन वाले म्यूटेक्स, क्रिटिकल सेक्शन और सिग्नल हैं। म्यूटेक्स अच्छे होते हैं जब आप यह सुनिश्चित करना चाहते हैं कि आप केवल कुछ कर रहे हैं। सिग्नल अच्छे हैं जब आप यह सुनिश्चित करना चाहते हैं कि किसी और ने कुछ करना समाप्त कर दिया है। साझा संसाधनों को कम करने से अप्रत्याशित व्यवहार को रोकने में भी मदद मिल सकती है

दौड़ की स्थिति का पता लगाना मुश्किल हो सकता है, लेकिन कुछ संकेत हैं। कोड जो नींद पर बहुत निर्भर करता है, दौड़ की स्थिति से ग्रस्त है, इसलिए पहले प्रभावित कोड में सोने के लिए कॉल की जाँच करें। विशेष रूप से लंबी नींद जोड़ना भी डिबगिंग के लिए इस्तेमाल किया जा सकता है और घटनाओं के एक विशेष क्रम को मजबूर करने के लिए। यह व्यवहार को पुन: पेश करने के लिए उपयोगी हो सकता है, यह देखने के लिए कि क्या आप चीजों के समय को बदलकर गायब हो सकते हैं, और जगह में समाधानों के परीक्षण के लिए। डिबगिंग के बाद नींद को हटा दिया जाना चाहिए।

हस्ताक्षर संकेत है कि एक दौड़ हालत है, हालांकि, अगर वहाँ एक समस्या है कि केवल कुछ मशीनों पर रुक-रुक कर होती है। सामान्य बग क्रैश और गतिरोध होंगे। लॉगिंग के साथ, आपको प्रभावित क्षेत्र को खोजने और वहां से वापस काम करने में सक्षम होना चाहिए।


10

Microsoft ने वास्तव में दौड़ की स्थिति और गतिरोध के इस मामले पर एक बहुत विस्तृत लेख प्रकाशित किया है । इसमें से सबसे संक्षेप सार शीर्षक पैराग्राफ होगा:

एक दौड़ की स्थिति तब होती है जब दो धागे एक ही समय में एक साझा चर का उपयोग करते हैं। पहला धागा चर को पढ़ता है, और दूसरा धागा चर से समान मूल्य को पढ़ता है। फिर पहला धागा और दूसरा धागा मूल्य पर अपना संचालन करते हैं, और वे यह देखने के लिए दौड़ते हैं कि कौन सा धागा साझा चर पर अंतिम मान लिख सकता है। थ्रेड का मान जो उसके मान को अंतिम रूप से लिखता है, वह संरक्षित है, क्योंकि थ्रेड उस मान पर लिख रहा है, जो पिछले थ्रेड ने लिखा था।


5

एक दौड़ की स्थिति क्या है?

वह स्थिति जब प्रक्रिया गंभीर रूप से अन्य घटनाओं के अनुक्रम या समय पर निर्भर होती है।

उदाहरण के लिए, प्रोसेसर ए और प्रोसेसर बी दोनों को उनके निष्पादन के लिए समान संसाधन की आवश्यकता है

आप उनका पता कैसे लगाते हैं?

स्वचालित रूप से दौड़ की स्थिति का पता लगाने के लिए उपकरण हैं:

आप उन्हें कैसे संभालेंगे?

रेस स्थिति से संभाला जा सकता है Mutex या Semaphores । वे एक ताला के रूप में कार्य करते हैं जो रेस की स्थिति को रोकने के लिए एक प्रक्रिया को कुछ आवश्यकताओं के आधार पर संसाधन प्राप्त करने की अनुमति देता है।

आप उन्हें होने से कैसे रोकेंगे?

दौड़ की स्थिति को रोकने के लिए विभिन्न तरीके हैं, जैसे कि महत्वपूर्ण धारा से बचाव

  1. कोई भी दो प्रक्रिया एक साथ उनके महत्वपूर्ण क्षेत्रों के अंदर नहीं होती है। ( पारस्परिक बहिष्करण)
  2. गति या सीपीयू की संख्या के बारे में कोई धारणा नहीं बनाई गई है।
  3. इसके महत्वपूर्ण क्षेत्र के बाहर चलने वाली कोई भी प्रक्रिया जो अन्य प्रक्रियाओं को अवरुद्ध नहीं करती है।
  4. किसी भी प्रक्रिया को अपने महत्वपूर्ण क्षेत्र में प्रवेश करने के लिए हमेशा इंतजार नहीं करना पड़ता है। (बी संसाधनों का इंतजार करता है, बी सी संसाधनों का इंतजार करता है, सी ए संसाधनों का इंतजार करता है)

2

एक दौड़ की स्थिति एक अवांछनीय स्थिति है जो तब होती है जब कोई उपकरण या सिस्टम एक ही समय में दो या दो से अधिक ऑपरेशन करने का प्रयास करता है, लेकिन डिवाइस या सिस्टम की प्रकृति के कारण, संचालन उचित क्रम में किया जाना चाहिए सही ढंग से किया

कंप्यूटर मेमोरी या स्टोरेज में, एक दौड़ की स्थिति हो सकती है यदि बड़ी मात्रा में डेटा को पढ़ने और लिखने की आज्ञा लगभग एक ही समय में प्राप्त होती है, और मशीन पुराने डेटा अभी भी कुछ या सभी पुराने डेटा को अधिलेखित करने का प्रयास करती है। पढ़ें। परिणाम निम्न में से एक या अधिक हो सकता है: एक कंप्यूटर दुर्घटना, एक "अवैध संचालन," अधिसूचना और कार्यक्रम का बंद होना, पुराने डेटा को पढ़ने में त्रुटियां, या नए डेटा लिखने में त्रुटियां।


2

यहाँ शास्त्रीय बैंक खाता शेष उदाहरण दिया गया है जो जावा में थ्रेड्स को आसानी से समझने के लिए newbies को रेस की स्थितियों में मदद करेगा:

public class BankAccount {

/**
 * @param args
 */
int accountNumber;
double accountBalance;

public synchronized boolean Deposit(double amount){
    double newAccountBalance=0;
    if(amount<=0){
        return false;
    }
    else {
        newAccountBalance = accountBalance+amount;
        accountBalance=newAccountBalance;
        return true;
    }

}
public synchronized boolean Withdraw(double amount){
    double newAccountBalance=0;
    if(amount>accountBalance){
        return false;
    }
    else{
        newAccountBalance = accountBalance-amount;
        accountBalance=newAccountBalance;
        return true;
    }
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    BankAccount b = new BankAccount();
    b.accountBalance=2000;
    System.out.println(b.Withdraw(3000));

}

1

आप दौड़ की स्थिति को रोक सकते हैं , यदि आप "परमाणु" वर्गों का उपयोग करते हैं। कारण सिर्फ इतना है कि थ्रेड अलग-अलग ऑपरेशन नहीं करते और सेट करते हैं, उदाहरण नीचे है:

AtomicInteger ai = new AtomicInteger(2);
ai.getAndAdd(5);

नतीजतन, आपके पास लिंक "एआई" में 7 होंगे। हालाँकि आपने दो क्रियाएं की थीं, लेकिन दोनों ऑपरेशन एक ही धागे की पुष्टि करते हैं और कोई भी अन्य धागा इस पर हस्तक्षेप नहीं करेगा, इसका मतलब है कि कोई दौड़ की स्थिति नहीं है!


0

दौड़ की स्थिति की बेहतर समझ के लिए इस मूल उदाहरण का प्रयास करें:

    public class ThreadRaceCondition {

    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Account myAccount = new Account(22222222);

        // Expected deposit: 250
        for (int i = 0; i < 50; i++) {
            Transaction t = new Transaction(myAccount,
                    Transaction.TransactionType.DEPOSIT, 5.00);
            t.start();
        }

        // Expected withdrawal: 50
        for (int i = 0; i < 50; i++) {
            Transaction t = new Transaction(myAccount,
                    Transaction.TransactionType.WITHDRAW, 1.00);
            t.start();

        }

        // Temporary sleep to ensure all threads are completed. Don't use in
        // realworld :-)
        Thread.sleep(1000);
        // Expected account balance is 200
        System.out.println("Final Account Balance: "
                + myAccount.getAccountBalance());

    }

}

class Transaction extends Thread {

    public static enum TransactionType {
        DEPOSIT(1), WITHDRAW(2);

        private int value;

        private TransactionType(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }
    };

    private TransactionType transactionType;
    private Account account;
    private double amount;

    /*
     * If transactionType == 1, deposit else if transactionType == 2 withdraw
     */
    public Transaction(Account account, TransactionType transactionType,
            double amount) {
        this.transactionType = transactionType;
        this.account = account;
        this.amount = amount;
    }

    public void run() {
        switch (this.transactionType) {
        case DEPOSIT:
            deposit();
            printBalance();
            break;
        case WITHDRAW:
            withdraw();
            printBalance();
            break;
        default:
            System.out.println("NOT A VALID TRANSACTION");
        }
        ;
    }

    public void deposit() {
        this.account.deposit(this.amount);
    }

    public void withdraw() {
        this.account.withdraw(amount);
    }

    public void printBalance() {
        System.out.println(Thread.currentThread().getName()
                + " : TransactionType: " + this.transactionType + ", Amount: "
                + this.amount);
        System.out.println("Account Balance: "
                + this.account.getAccountBalance());
    }
}

class Account {
    private int accountNumber;
    private double accountBalance;

    public int getAccountNumber() {
        return accountNumber;
    }

    public double getAccountBalance() {
        return accountBalance;
    }

    public Account(int accountNumber) {
        this.accountNumber = accountNumber;
    }

    // If this method is not synchronized, you will see race condition on
    // Remove syncronized keyword to see race condition
    public synchronized boolean deposit(double amount) {
        if (amount < 0) {
            return false;
        } else {
            accountBalance = accountBalance + amount;
            return true;
        }
    }

    // If this method is not synchronized, you will see race condition on
    // Remove syncronized keyword to see race condition
    public synchronized boolean withdraw(double amount) {
        if (amount > accountBalance) {
            return false;
        } else {
            accountBalance = accountBalance - amount;
            return true;
        }
    }
}

0

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

हालांकि, दौड़ की स्थिति का पता लगाने के लिए एक उपकरण का उपयोग करके, इसे हानिकारक दौड़ की स्थिति के रूप में देखा जाएगा।

रेस स्थिति यहां पर अधिक जानकारी, http://msdn.microsoft.com/en-us/magazine/cc546569.aspx


आपका उत्तर किस भाषा पर आधारित है?
मिकएमबी

सच कहूँ तो मुझे ऐसा लगता है कि यदि आपके पास प्रति दौड़ की स्थिति है , तो आप अपने कोड को कड़ाई से नियंत्रित नहीं कर रहे हैं। यह, जबकि यह आपके सैद्धांतिक मामले में एक मुद्दा नहीं हो सकता है, जिस तरह से आप सॉफ्टवेयर डिजाइन और विकसित करने के साथ बड़े मुद्दों का सबूत है। जल्दी या बाद में दर्दनाक दौड़ हालत कीड़े का सामना करने की अपेक्षा करें।
इंजीनियर

0

एक ऑपरेशन पर विचार करें, जिसे गणना में वृद्धि के रूप में जल्द ही प्रदर्शित करना है। यानी।, जैसे ही काउंटरथ्रेड मूल्य बढ़ाता है DisplayThread को हाल ही में अपडेट किए गए मूल्य को प्रदर्शित करने की आवश्यकता होती है।

int i = 0;

उत्पादन

CounterThread -> i = 1  
DisplayThread -> i = 1  
CounterThread -> i = 2  
CounterThread -> i = 3  
CounterThread -> i = 4  
DisplayThread -> i = 4

यहाँ CounterThread को बार-बार लॉक मिलता है और DisplayThread को प्रदर्शित करने से पहले मान को अद्यतन करता है। यहाँ एक रेस कंडीशन मौजूद है। Synchronzation का उपयोग करके रेस कंडीशन को हल किया जा सकता है


0

एक दौड़ की स्थिति एक अवांछनीय स्थिति है जो तब होती है जब दो या अधिक प्रक्रिया एक ही समय में साझा किए गए डेटा तक पहुंच सकते हैं और बदल सकते हैं। ऐसा इसलिए हुआ क्योंकि एक संसाधन के लिए परस्पर विरोधी एक्सेस थे। गंभीर स्थिति समस्या दौड़ की स्थिति का कारण बन सकती है। प्रक्रिया के बीच गंभीर स्थिति को हल करने के लिए हम एक समय में केवल एक प्रक्रिया को निकालते हैं जो महत्वपूर्ण अनुभाग को निष्पादित करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.