2010-06-26 12 views
6

मैं मल्टीथ्रेडिंग के लिए नया हूं, और मैंने यह कोड लिखा है जो समवर्ती रूप से थ्रेड वृद्धि और एक चर मुद्रित करके संख्या 1-10000 प्रिंट करता है।वास्तव में सिर्फ सिंटैक्टिक चीनी 'सिंक्रनाइज़' है?

यहाँ कोड मैं का उपयोग कर रहा है:

package threadtest; 

public class Main{ 

    static int i=0; 
    static Object lock=new Object(); 

    private static class Incrementer extends Thread{ 

     @Override 
     public void run(){ 
      while (true){ 
       synchronized(lock){ 
         if (i>=10000) 
          break; 
         i++; 
         System.out.println(i); 
       } 
      }    
     } 
    } 


    public static void main(String[] args) { 
     new Incrementer().start(); 
     new Incrementer().start(); 
     new Incrementer().start(); 
     new Incrementer().start(); 
     new Incrementer().start(); 
     new Incrementer().start(); 
    } 
} 

यह काम करता है - मैं उत्पादन की जाँच करने के लिए एक परीक्षण कार्यक्रम को लिखा था, और संख्या मुद्रित क्रम में वास्तव में 1-10000 हैं।

मेरा प्रश्न यह है: मैंने सुना है कि synchronized केवल वाक्य रचनात्मक चीनी है। लेकिन मैं इसका उपयोग किए बिना सफल परिणाम प्राप्त नहीं कर सकता। मैं क्या खो रहा हूँ?

+6

यह निश्चित रूप से नहीं है। क्या आप उन स्रोतों का हवाला दे सकते हैं जहां आपने यह सुना है? – BalusC

+1

@ बालससी: स्वीकृत उत्तर देखें। मुझे लगता है कि स्रोत सिंक्रनाइज़ * विधियों * को सिंटैक्टिक चीनी के रूप में संदर्भित कर रहे थे - मुझे यकीन नहीं है कि यह बिल्कुल सही है या नहीं, लेकिन कम से कम यह मेरे निष्कर्षों के विपरीत नहीं है जैसा मैंने सोचा था। @ स्काफमैन: मैं जानता था कि मैं सिंक्रनाइज़ किए बिना 'सिंक्रनाइज़ किए गए' के ​​बिना गलत कर रहा था :) – Cam

+0

@ एक विधि पर @ अनुबंधित 'सिंक्रनाइज़', विधि के शरीर को सिंक्रनाइज़ (इस) में डालने जैसा ही कम है {...} '(या एक स्थैतिक विधि के लिए 'सिंक्रनाइज़ (MyClass.class) {...}')। (यह वर्ग फ़ाइलों में अलग-अलग प्रतिनिधित्व करता है, लेकिन यह आपको आमतौर पर चिंता नहीं करना चाहिए।) –

उत्तर

14

synchronized किसी भी चीज़ के लिए वाक्य रचनात्मक चीनी नहीं है। synchronized कीवर्ड का उपयोग किए बिना जावा में ताले काम करने का कोई तरीका नहीं है।

जावा में ताले में एक प्रकार की "सिंटेक्टिक चीनी" कहां है, synchronized दोनों ब्लॉक (जैसे आपने इसे ऊपर किया है) और पूरी विधियों पर लागू कर सकते हैं। निम्नलिखित दो तरीकों अर्थ विज्ञान में बराबर हैं:

synchronized void method1() { 
    // ... do stuff ... 
} 

void method2() { 
    synchronized(this) { 
    // ... do stuff ... 
    } 
} 

तो क्यों आप पहली बार के बजाय दूसरे संस्करण करना चाहेगा?

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

धन्यवाद, यह समझ में आता है। इसे साफ़ करने के लिए खुशी हुई :) – Cam

+0

एक ब्लॉक के साथ आप लॉक के रूप में कुछ निजी वस्तु का उपयोग कर सकते हैं, जो बाहरी कोड से हस्तक्षेप को रोकता है। – starblue

+0

अच्छा बिंदु। मैं इसे जवाब में जोड़ूंगा, स्टारब्लू। –

1

ऐसा लगता है जैसे आपके स्रोत गलत हैं। syncrhonized कीवर्ड का उपयोग करना महत्वपूर्ण है - और सही ढंग से उपयोग करें - थ्रेड-सुरक्षित कोड लिखते समय। और ऐसा लगता है जैसे आपके स्वयं के प्रयोग इसे सहन करते हैं।

जावा में तुल्यकालन के बारे में अधिक के लिए:

Java Synchronized Methods

Java Locks and Synchronized Statements

0

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

synchronized(MyClass.class){ 
//code to be executed in the static context 
} 

का उपयोग कर वर्ग स्तर पर होना चाहिए अगर उदाहरण विधि में ब्लॉक तो तुल्यकालन एक वस्तु का एक उदाहरण का उपयोग करना चाहिए सिंक्रनाइज़ किया जा रहा है जो सभी धागे के बीच साझा किया जाता है। अधिकांश पोपल दूसरे बिंदु के साथ गलत हो जाते हैं क्योंकि यह आपके कोड में दिखाई देता है जहां सिंक्रनाइज़ेशन एक ऑब्जेक्ट की बजाय अलग-अलग ऑब्जेक्ट्स पर दिखाई देता है।

1

वास्तव में जावा 5 के रूप में आप (औपचारिक रूप से) java.util.concurrent में औजारों का एक वैकल्पिक सेट है। अधिक जानकारी के लिए here देखें। जैसा कि आलेख में विस्तृत है, जावा के भाषा स्तर पर प्रदान किए गए मॉनीटर लॉकिंग मॉडल में कई महत्वपूर्ण सीमाएं हैं और इस पर तर्क करना मुश्किल हो सकता है कि परस्पर निर्भर वस्तुओं का एक जटिल सेट और लाइव लॉक को वास्तविक लॉक बनाने के संबंधों को लॉक करना कितना मुश्किल हो सकता है। extremley उपयोगी वाक्यात्मक चीनी - java.util.concurrent पुस्तकालय जो प्रोग्रामर जो POSIX सिस्टम की तरह

1
बेशक

, "सिंक्रनाइज़" में अनुभव प्राप्त हुआ है के लिए और अधिक परिचित हो सकते हैं अर्थ विज्ञान ताला लगा प्रस्तावों बस वाक्यात्मक चीनी है।

आप शुगर फ्री जावा कार्यक्रमों चाहते हैं, तो आप सीधे जावा बाइट कोड में monitorenter, monitorexit, ताला, और अनलॉक संचालन VM Specifications 8.13 Locks and Synchronization

वहाँ में संदर्भित लेखन किया जाना चाहिए प्रत्येक वस्तु से जुड़ा एक ताला है। जावा प्रोग्रामिंग भाषा को अलग लॉक करने और संचालन अनलॉक करने का तरीका प्रदान नहीं करती है; इसके बजाय, वे हैं जो उच्च स्तर संरचनाओं द्वारा निहित प्रदर्शन करते हैं जो हमेशा ऐसे परिचालनों को सही ढंग से जोड़ना चाहते हैं। (जावा आभासी मशीन है, तथापि, अलग monitorenter और monitorexit निर्देश है कि ताला को लागू करने और संचालन अनलॉक प्रदान करता है।)

सिंक्रनाइज़ बयान किसी ऑब्जेक्ट को संदर्भ गणना करता है; यह उस ऑब्जेक्ट पर लॉक ऑपरेशन निष्पादित करने का प्रयास करता है और आगे नहीं बढ़ता है जब तक लॉक ऑपरेशन सफलतापूर्वक पूरा नहीं हो जाता है। (ए ताला आपरेशन देरी हो सकती है क्योंकि ताले जब तक कुछ अन्य धागा एक या अधिक अनलॉक आपरेशनों। प्रदर्शन करने के लिए तैयार है भाग लेने से मुख्य स्मृति रोका जा सकता है के बारे में नियम) ताला आपरेशन के बाद की जा चुकी है, सिंक्रनाइज़ कथन का शरीर निष्पादित है। आम तौर पर, जावा प्रोग्रामिंग भाषा के लिए एक संकलक सुनिश्चित करता है कि ताला आपरेशन एक monitorenter अनुदेश द्वारा कार्यान्वित निष्पादित सिंक्रनाइज़ बयान के शरीर के निष्पादन से पहले अनलॉक एक monitorexit अनुदेश जब भी द्वारा कार्यान्वित आपरेशन के अनुरूप है सिंक्रनाइज़ कथन पूरा करता है, चाहे पूरा हो रहा है या अचानक है।

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

सर्वश्रेष्ठ अभ्यास है कि अगर एक चर कभी एक धागा और इस्तेमाल किया या किसी अन्य द्वारा आवंटित द्वारा आवंटित किया जा रहा है, तो सभी कि चर के लिए पहुँचता सिंक्रनाइज़ तरीकों या सिंक्रनाइज़ बयान में संलग्न किया जाना चाहिए।

हालांकि ताले के जावा प्रोग्रामिंग भाषा के लिए एक संकलक सामान्य रूप से की गारंटी देता है संरचित उपयोग (धारा 7.14, "तुल्यकालन" देखें), बात की कोई गारंटी है कि सभी कोड जावा आभासी मशीन इस आज्ञा का पालन करेंगे को प्रस्तुत है संपत्ति। जावा आभासी मशीन के क्रियान्वयन की अनुमति है लेकिन की आवश्यकता नहीं दोनों संरचित लॉकिंग की गारंटी के बाद दो नियमों के लागू करने के लिए।

टी एक धागा और एल एक ताला होना बनें। तब:

  1. एक विधि मंगलाचरण के दौरान एल पर टी द्वारा किया जाता संख्या के बराबर की विधि मंगलाचरण के दौरान एल पर टी द्वारा किया आपरेशन अनलॉक करना होगा ताला आपरेशन की संख्या चाहे विधि मंगलाचरण पूरा करता सामान्य रूप से या अचानक।

  2. एक विधि मंगलाचरण के दौरान किसी भी बिंदु पर अनलॉक के बाद से एल पर टी द्वारा किया जाता विधि मंगलाचरण के संचालन की संख्या विधि मंगलाचरण के बाद से एल पर टी द्वारा किया जाता ताला आपरेशन के संख्या से अधिक हो सकती है।

कम औपचारिक शब्दों में, एक विधि मंगलाचरण एल पर हर अनलॉक आपरेशन एल पर कुछ पूर्ववर्ती ताला आपरेशन से मेल खाना चाहिए

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