मेरे उत्तर में कुछ कार्यान्वयन विशिष्ट जानकारी है। यह सूर्य जेवीएम और अन्य थ्रेड लाइब्रेरी व्यवहार के मेरे कामकाजी ज्ञान पर आधारित है।
यदि दो निर्माता धागे सूचित करते हैं, तो क्या यह गारंटी है कि दो अलग प्रतीक्षा उपभोक्ता धागे जाग जाएंगे?
नहीं, यह नहीं है। इस बात की कोई गारंटी नहीं है कि कोई भी उपभोक्ता जाग जाएगा। गारंटी क्या है कि यदि 2 धागे इंतजार कर रहे हैं, तो 2 अलग धागे को रन कतार में रखा जाएगा।
या यह हो सकता है कि दो notify()
रों एक दूसरे के कारण ही उपभोक्ताओं धागा दो बार Wakeup के लिए पंक्तिबद्ध किए जाने के बाद शीघ्र ही निकाल दिया?
संख्या दो notify()
कॉल एक ही उपभोक्ता धागे को दो बार कतारबद्ध नहीं करेगा। हालांकि, यह एक थ्रेड को जागृत करने का कारण बन सकता है और अन्य धागे इंतजार नहीं कर सकते हैं, इसलिए दूसरा notify()
कॉल कुछ भी नहीं कर सकता है। बेशक धागा जागृत हो सकता था और फिर फिर से इंतजार कर रहा था और फिर दूसरी notify()
उस तरह से कॉल करें, लेकिन मुझे नहीं लगता कि आप यही पूछ रहे हैं।
क्या जावा में एक बार थ्रेड को जागने के लिए कुछ परमाणु आंतरिक ऑपरेशन होता है?
हां। Thread
कोड में कई सिंक्रनाइज़ेशन अंक हैं। एक बार थ्रेड अधिसूचित होने के बाद इसे wait
कतार से बाहर ले जाया जाता है। notify()
पर भविष्य की कॉल wait
कतार में दिखाई देगी और धागे को नहीं मिलेगी।
एक और महत्वपूर्ण बिंदु। निर्माता/उपभोक्ता मॉडल के साथ, हमेशा सुनिश्चित करें कि आप while
लूप में स्थिति का परीक्षण कर रहे हैं। इसका कारण यह है कि उपभोक्ताओं के साथ दौड़ की स्थिति है जो ताला पर अवरुद्ध हैं लेकिन इस स्थिति पर इंतजार नहीं कर रहे हैं।
synchronized (workQueue) {
// you must do a while here
while (workQueue.isEmpty()) {
workQueue.wait();
}
workQueue.remove();
}
Consumer1
workQueue
पर इंतजार किया जा सकता है। Consumer2
synchronized
पर लेकिन रन-कतार में अवरुद्ध किया जा सकता है। अगर workQueue
और workQueue.notify()
में कुछ डाल दिया जाता है। Consumer2
अब रन-कतार में रखा गया है लेकिन Consumer1
के पीछे है जो पहले वहां है। यह एक आम कार्यान्वयन है। तो Consumer1
workQueue
से आइटम को हटा देता है जो Consumer2
के बारे में अधिसूचित किया गया था। Consumer2
को फिर से परीक्षण करना है यदि workQueue
खाली है अन्यथा remove()
फेंक देगा क्योंकि कतार फिर से खाली है। more details of the race के लिए यहां देखें।
यह जानना भी महत्वपूर्ण है कि नकली जागरूकता दस्तावेज की गई है ताकि while
लूप wait()
कॉल के बिना जागने वाले थ्रेड के खिलाफ सुरक्षा करता है।
यह सब कहा गया है, अगर आप BlockingQueue
का उपयोग कर अपने निर्माता/उपभोक्ता कोड को अन्य उत्तरों में अनुशंसित कर सकते हैं तो आपको ऐसा करना चाहिए। BlockingQueue
कोड पहले से ही इन सभी समस्याओं का समाधान कर चुका है।
आप केवल ब्लॉकिंगक्यूयू कार्यान्वयन का उपयोग क्यों नहीं करते? –
मैं मॉरीसिओ से सहमत हूं। प्रतीक्षा करें()/सूचित करें() यदि संभव हो तो साफ़ करें - यह रेसिंग की स्थिति का एक हॉर्नेट घोंसला है, खराब दस्तावेज एपीआई और "नकली wakeups"। –