हाल ही में, मैं थ्रेड क्लास पर सिंक्रनाइज़ेशन की एक दिलचस्प विशेषता के बारे में आया। मैंने एक वर्ग बनाया जो थ्रेड विरासत में मिला और आंतरिक तुल्यकालन के लिए इसमें लॉक ऑब्जेक्ट पैटर्न का उपयोग किया। कुछ बिंदु पर, यह मुझे प्रतीत हुआ कि लॉक ऑब्जेक्ट कोड को फुला रहा था, और चूंकि मैं बहुत कम संख्या में स्थानों से निर्मित स्ट्रीम का उपयोग करता हूं, मैंने इसे बाहर फेंक दिया, सिंक्रनाइज़ किए गए तरीकों की जगह और इसके साथ प्रतीक्षा करें / सूचित करें। यदि आप जानना चाहते हैं कि "कोड" के इस छोटे से उल्लंघन से क्या हुआ - बिल्ली का स्वागत।
सामान्य तौर पर, कुछ भी अच्छा नहीं आया। कार्यक्रम ने सामान्य रूप से लगभग हमेशा काम किया, लेकिन सीआई समय-समय पर गलत व्यवहार करने लगे।
थ्रेड क्लास पर एक त्वरित नज़र से पता चला है कि जावा सिंक्रोनाइज़ेशन तंत्र का उपयोग थ्रेड क्लास में ही किया जाता है, अर्थात् जॉइन विधि में:
public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
वास्तव में, सूचित () स्वयं को थ्रेड क्लास में नहीं कहा जाता है, लेकिन थ्रेड फिनिश के बाद cpp-code में कहा जाता है:
static void ensure_join(JavaThread* thread) {
इस प्रकार, दो समस्याएं पैदा होती हैं - अधिसूचित करके (), यदि आप भाग्यशाली नहीं हैं, तो आप जॉइन थ्रेड को जगाते हैं, जो डरावना नहीं है, लेकिन आप अपने धागे को नहीं जगाते हैं, जो डरावना है।
और दूसरा, धागा खत्म होने के बाद, इस पर InformAll () को कॉल किया जाता है, जो आपके सभी प्रतीक्षा () को जगा देगा, हालांकि आप स्पष्ट रूप से नहीं करना चाहेंगे।
सामान्य तौर पर, शुक्रवार की कहानी की नैतिकता सामान्य है - एक लॉक ऑब्जेक्ट का उपयोग करें यदि कम से कम एक संभावित संभावना है कि आपके अलावा किसी अन्य व्यक्ति को आपकी कक्षा की वस्तुओं के साथ सिंक्रनाइज़ किया जाएगा। और यदि आप एक विदेशी वर्ग से विरासत में लेते हैं जो वस्तु नहीं है, तो निश्चित रूप से ऐसी संभावना है।