मेरे पास synchronized
कीवर्ड के उपयोग और महत्व के बारे में कुछ प्रश्न हैं ।
synchronized
कीवर्ड का महत्व क्या है ?- विधियाँ कब होनी चाहिए
synchronized
? - इसका प्रोग्राम और तार्किक रूप से क्या मतलब है?
मेरे पास synchronized
कीवर्ड के उपयोग और महत्व के बारे में कुछ प्रश्न हैं ।
synchronized
कीवर्ड का महत्व क्या है ?synchronized
?जवाबों:
synchronized
कीवर्ड अलग धागे पढ़ रहे हैं और एक ही चर, वस्तुओं और संसाधनों के लिए लिखने के बारे में सब है। यह जावा में एक तुच्छ विषय नहीं है, लेकिन यहां सूर्य से एक उद्धरण है:
synchronized
विधियाँ थ्रेड व्यवधान और मेमोरी संगतता त्रुटियों को रोकने के लिए एक सरल रणनीति को सक्षम करती हैं: यदि कोई ऑब्जेक्ट एक से अधिक थ्रेड के लिए दिखाई देता है, तो सभी उस ऑब्जेक्ट के वेरिएबल्स को पढ़ता या लिखता है जो सिंक्रनाइज़ किए गए तरीकों से किया जाता है।
एक बहुत, बहुत छोटे संक्षेप में: जब आपके पास दो धागे होते हैं जो एक ही 'संसाधन' को पढ़ और लिख रहे होते हैं foo
, तो नाम वाले एक चर कहते हैं , आपको यह सुनिश्चित करने की आवश्यकता है कि ये धागे एक परमाणु तरीके से चर तक पहुंचते हैं। synchronized
कीवर्ड के बिना , आपका थ्रेड 1 परिवर्तन थ्रेड 2 से बना foo
या खराब नहीं देख सकता है, यह केवल आधा बदला जा सकता है। यह वह नहीं होगा जो आप तार्किक रूप से उम्मीद करते हैं।
फिर, यह जावा में एक गैर-तुच्छ विषय है। अधिक जानने के लिए, SO और इंटरवेब के बारे में यहां विषयों का पता लगाएं:
इन विषयों की खोज तब तक करते रहें जब तक कि "ब्रायन गोएत्ज़" नाम स्थायी रूप से आपके मस्तिष्क में शब्द "संगामिति" से न जुड़ जाए ।
ठीक है, मुझे लगता है कि हमारे पास पर्याप्त सैद्धांतिक व्याख्याएं थीं, इसलिए इस कोड पर विचार करें
public class SOP {
public static void print(String s) {
System.out.println(s+"\n");
}
}
public class TestThread extends Thread {
String name;
TheDemo theDemo;
public TestThread(String name,TheDemo theDemo) {
this.theDemo = theDemo;
this.name = name;
start();
}
@Override
public void run() {
theDemo.test(name);
}
}
public class TheDemo {
public synchronized void test(String name) {
for(int i=0;i<10;i++) {
SOP.print(name + " :: "+i);
try{
Thread.sleep(500);
} catch (Exception e) {
SOP.print(e.getMessage());
}
}
}
public static void main(String[] args) {
TheDemo theDemo = new TheDemo();
new TestThread("THREAD 1",theDemo);
new TestThread("THREAD 2",theDemo);
new TestThread("THREAD 3",theDemo);
}
}
नोट: synchronized
अगले थ्रेड के कॉल टू मेथड टेस्ट () को तब तक रोकते हैं जब तक कि पिछले थ्रेड का निष्पादन समाप्त नहीं हो जाता। थ्रेड्स इस विधि को एक बार में एक्सेस कर सकते हैं। बिना synchronized
सभी धागे एक साथ इस विधि का उपयोग कर सकते हैं।
जब कोई थ्रेड ऑब्जेक्ट की सिंक्रोनाइज़्ड विधि 'टेस्ट' को बुलाता है (यहाँ ऑब्जेक्ट 'TheDemo' क्लास का एक उदाहरण है) यह उस ऑब्जेक्ट के लॉक को प्राप्त करता है, कोई भी नया थ्रेड उसी ऑब्जेक्ट के किसी भी सिंक्रोनाइज़ किए हुए तरीके को पिछले थ्रेड के रूप में नहीं कह सकता है। जिसने ताला प्राप्त कर लिया था वह ताला जारी नहीं करता है।
इसी तरह की बात तब होती है जब कक्षा के किसी भी स्थिर सिंक्रनाइज़ विधि को कहा जाता है। धागा वर्ग से जुड़े लॉक को प्राप्त करता है (इस मामले में उस वर्ग के उदाहरण के किसी भी गैर स्थिर सिंक्रनाइज़ विधि को किसी भी धागे से बुलाया जा सकता है क्योंकि वह ऑब्जेक्ट स्तर लॉक अभी भी उपलब्ध है)। कोई अन्य धागा वर्ग के किसी भी स्थिर सिंक्रनाइज़ विधि को कॉल करने में सक्षम नहीं होगा, जब तक कि क्लास स्तर का लॉक उस थ्रेड द्वारा जारी नहीं किया जाता है जो वर्तमान में लॉक रखता है।
सिंक्रनाइज़ के साथ आउटपुट
THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9
आउटपुट बिना सिंक्रनाइज़ किए गए
THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9
synchronized
, लेकिन मेमोरी संगतता को अनदेखा किया जाता है।
synchronized
कीवर्ड एक से अधिक थ्रेड से कोड या वस्तु के एक ब्लॉक को समवर्ती पहुँच रोकता है। के सभी तरीके Hashtable
हैं synchronized
, इसलिए केवल एक धागा उनमें से किसी को भी एक समय में निष्पादित कर सकता है।
synchronized
जैसे गैर- निर्माण का उपयोग करते समय HashMap
, आपको निरंतरता त्रुटियों को रोकने के लिए अपने कोड में थ्रेड-सेफ्टी फीचर्स का निर्माण करना चाहिए।
synchronized
इसका मतलब है कि एक बहु थ्रेडेड वातावरण में, एक ऑब्जेक्ट synchronized
विधि (एस) / ब्लॉक (ओं) synchronized
को एक ही समय में कोड के विधि (एस) / ब्लॉक (एस) तक पहुंचने के लिए दो धागे नहीं होने देता है । इसका मतलब यह है कि एक धागा पढ़ नहीं सकता है जबकि दूसरा धागा इसे अपडेट करता है।
इसके बजाय दूसरा धागा तब तक इंतजार करेगा जब तक कि पहला धागा अपना निष्पादन पूरा नहीं कर लेता। ओवरहेड गति है, लेकिन लाभ डेटा की स्थिरता की गारंटी है।
यदि आपका आवेदन सिंगल थ्रेडेड है, लेकिन synchronized
ब्लॉक लाभ प्रदान नहीं करता है।
synchronized
कीवर्ड जब विधि में प्रवेश एक ताला प्राप्त करने के लिए है, इसलिए है कि केवल एक धागा एक ही समय में विधि निष्पादित कर सकते हैं (दिए गए वस्तु उदाहरण के लिए, जब तक यह एक स्थिर तरीका है) एक धागे का कारण बनता है।
इसे अक्सर क्लास थ्रेड-सेफ कहा जाता है, लेकिन मैं कहूंगा कि यह एक व्यंजना है। हालांकि यह सच है कि सिंक्रनाइज़ेशन वेक्टर की आंतरिक स्थिति को दूषित होने से बचाता है, यह आमतौर पर वेक्टर के उपयोगकर्ता की बहुत मदद नहीं करता है।
इस पर विचार करो:
if (vector.isEmpty()){
vector.add(data);
}
भले ही शामिल तरीकों को सिंक्रनाइज़ किया जाता है, क्योंकि वे लॉक किए जा रहे हैं और व्यक्तिगत रूप से अनलॉक किए गए हैं, दो दुर्भाग्य से समय पर थ्रेड्स दो तत्वों के साथ एक वेक्टर बना सकते हैं।
इसलिए वास्तव में, आपको अपने एप्लिकेशन कोड में भी सिंक्रनाइज़ करना होगा।
क्योंकि विधि-स्तरीय सिंक्रनाइज़ेशन a) महंगा है, जब आपको इसकी आवश्यकता नहीं है और b) अपर्याप्त है जब आपको सिंक्रनाइज़ेशन की आवश्यकता होती है, तो अब अन-सिंक्रोनाइज़्ड रिप्लेसमेंट (वेक्टर के मामले में ArrayList) हैं।
अभी हाल ही में, संगामिति पैकेज जारी किया गया है, जिसमें कई चतुर उपयोगिताओं के साथ मल्टी-थ्रेडिंग मुद्दों का ध्यान रखा गया है।
जावा में सिंक्रोनाइज़्ड कीवर्ड को थ्रेड-सेफ्टी के साथ करना होता है, यानी जब एक ही वेरिएबल एक ही वेरिएबल को पढ़ता या लिखता है।
यह सीधे (एक ही चर को एक्सेस करके) या परोक्ष रूप से हो सकता है (एक वर्ग का उपयोग करके जो दूसरे वर्ग का उपयोग करता है जो एक ही चर का उपयोग करता है)।
सिंक्रनाइज़ किए गए कीवर्ड का उपयोग कोड के एक ब्लॉक को परिभाषित करने के लिए किया जाता है जहां कई धागे एक ही चर को सुरक्षित तरीके से एक्सेस कर सकते हैं।
सिंटैक्स-वार synchronized
कीवर्ड एक Object
पैरामीटर के रूप में लेता है (जिसे लॉक ऑब्जेक्ट कहा जाता है ), जिसे बाद में ए { block of code }
।
जब निष्पादन इस कीवर्ड का सामना करता है, तो वर्तमान थ्रेड लॉक ऑब्जेक्ट को "लॉक / अधिग्रहित / लेने" (आपकी पिक लेने) की कोशिश करता है और लॉक प्राप्त होने के बाद संबंधित ब्लॉक के कोड को निष्पादित करता है।
सिंक्रनाइज़ कोड ब्लॉक के अंदर चर के लिए कोई भी लिखता है, हर दूसरे धागे को दिखाई देने की गारंटी है जो समान लॉक ऑब्जेक्ट का उपयोग करके सिंक्रनाइज़ कोड ब्लॉक के अंदर कोड निष्पादित करता है ।
एक समय में केवल एक धागा ही लॉक को पकड़ सकता है, उस समय के दौरान एक ही लॉक ऑब्जेक्ट को प्राप्त करने की कोशिश करने वाले अन्य सभी धागे प्रतीक्षा करेंगे ( किसी भी निष्पादन को रोकें)। लॉक तब रिलीज़ होगा जब निष्पादन सिंक्रनाइज़ कोड ब्लॉक से बाहर निकलता है।
synchronized
एक विधि परिभाषा में कीवर्ड जोड़ना लॉक ऑब्जेक्ट जा रहा है this
(उदाहरण के तरीकों के लिए) और ClassInQuestion.getClass()
(वर्ग विधियों के लिए ) के साथ एक सिंक्रनाइज़ कोड ब्लॉक में लिपटे जा रहे पूरे विधि निकाय के बराबर है ।
- इंस्टेंट विधि एक ऐसी विधि है जिसमें static
कीवर्ड नहीं होता है ।
- क्लास मेथड एक ऐसी विधि है जिसमें static
कीवर्ड होता है।
सिंक्रनाइज़ेशन के बिना, यह गारंटी नहीं है कि किस क्रम में रीड और राइट होता है, संभवतः चर के साथ कचरा छोड़ रहा है।
(उदाहरण के लिए एक चर एक धागे से लिखे गए बिट्स के आधे और दूसरे धागे द्वारा लिखे गए आधे बिट्स के साथ समाप्त हो सकता है, चर को ऐसी स्थिति में छोड़ देता है कि दोनों में से किसी भी धागे ने लिखने की कोशिश नहीं की, लेकिन दोनों का एक संयुक्त गड़बड़।
एक थ्रेड (दीवार-घड़ी का समय) से पहले एक थ्रेड ऑपरेशन में इसे पूरा करने के लिए पर्याप्त नहीं है, एक अन्य थ्रेड इसे पढ़ता है, क्योंकि हार्डवेयर चर के मूल्य को कैश कर सकता था, और रीडिंग थ्रेड को कैश्ड मान के बजाय जो लिखा गया था वह दिखाई देगा यह।
इस प्रकार जावा के मामले में, आपको यह सुनिश्चित करने के लिए जावा मेमोरी मॉडल का पालन करना होगा कि थ्रेडिंग त्रुटियां न हों।
दूसरे शब्दों में: तुल्यकालन, परमाणु संचालन या वर्गों का उपयोग करें जो उन्हें डाकू के तहत आपके लिए उपयोग करते हैं।
सूत्रों का कहना है
http://docs.oracle.com/javase/specs/jls/se8/html/index.html
Java® भाषा विशिष्टता, 2015-02-13
इसे एक तरह का टर्नस्टाइल समझें, जैसा कि आप फुटबॉल ग्राउंड में देख सकते हैं। वहाँ लोगों के समानांतर स्टीम प्राप्त करना चाहते हैं, लेकिन टर्नस्टाइल में वे 'सिंक्रनाइज़' हैं। एक समय में केवल एक व्यक्ति के माध्यम से प्राप्त कर सकते हैं। उन सभी के माध्यम से प्राप्त करना चाहते हैं, लेकिन उन्हें इंतजार करना पड़ सकता है।
सिंक्रनाइज़ कीवर्ड क्या है?
थ्रेड मुख्य रूप से फ़ील्ड्स और ऑब्जेक्ट्स रेफरेंस फ़ील्ड्स तक पहुँच साझा करके संवाद करते हैं। संचार का यह रूप अत्यंत कुशल है, लेकिन दो प्रकार की त्रुटियों को संभव बनाता है: थ्रेड इंटरफेरेंस और मेमोरी संगति त्रुटियों । इन त्रुटियों को रोकने के लिए आवश्यक उपकरण सिंक्रनाइज़ेशन है।
सिंक्रोनाइज़्ड ब्लॉक्स या तरीके थ्रेड इंटरफेरेंस को रोकते हैं और सुनिश्चित करते हैं कि डेटा सुसंगत है। किसी भी समय, केवल एक धागा एक लॉक प्राप्त करके एक सिंक्रनाइज़ ब्लॉक या विधि ( महत्वपूर्ण अनुभाग ) तक पहुंच सकता है । अन्य थ्रेड महत्वपूर्ण खंडों तक पहुंचने के लिए लॉक जारी करने की प्रतीक्षा करेंगे ।
तरीके कब सिंक्रनाइज़ किए जाते हैं?
जब आप synchronized
विधि परिभाषा या घोषणा में जोड़ते हैं तो विधियाँ सिंक्रनाइज़ की जाती हैं । आप एक विधि के साथ कोड के एक विशेष ब्लॉक को भी सिंक्रनाइज़ कर सकते हैं।
इसका क्या मतलब है कि व्याकरणिक और तार्किक रूप से समर्थक?
इसका मतलब है कि केवल एक धागा लॉक प्राप्त करके महत्वपूर्ण अनुभाग तक पहुंच सकता है । जब तक यह थ्रेड इस लॉक को रिलीज़ नहीं करता, तब तक अन्य सभी थ्रेड्स को लॉक प्राप्त करने के लिए इंतजार करना होगा। उनके पास महत्वपूर्ण खंड में प्रवेश प्राप्त करने के लिए ताला नहीं है।
यह एक जादू के साथ नहीं किया जा सकता है। यह प्रोग्रामर की जिम्मेदारी है कि वह आवेदन में महत्वपूर्ण सेक्शन (वर्गों) की पहचान करे और उसके अनुसार उसकी सुरक्षा करे। जावा आपके आवेदन की सुरक्षा के लिए एक ढांचा प्रदान करता है, लेकिन कहाँ और क्या सभी वर्गों की रक्षा करना प्रोग्रामर की जिम्मेदारी है।
जावा प्रलेखन पृष्ठ से अधिक जानकारी
आंतरिक ताले और तुल्यकालन:
आंतरिक आंतरिक लॉक या मॉनिटर लॉक के रूप में जानी जाने वाली आंतरिक इकाई के आसपास सिंक्रोनाइज़ेशन का निर्माण किया जाता है। आंतरिक ताले तुल्यकालन के दोनों पहलुओं में एक भूमिका निभाते हैं: किसी वस्तु की स्थिति के लिए विशेष पहुंच को लागू करना और ऐसा होना-पहले संबंधों को स्थापित करना जो दृश्यता के लिए आवश्यक हैं।
हर वस्तु में एक आंतरिक ताला लगा होता है । कन्वेंशन द्वारा, एक थ्रेड जिसे किसी ऑब्जेक्ट के फ़ील्ड में अनन्य और लगातार एक्सेस की आवश्यकता होती है, उन्हें एक्सेस करने से पहले ऑब्जेक्ट के आंतरिक लॉक का अधिग्रहण करना पड़ता है, और फिर आंतरिक लॉक को तब जारी करते हैं जब यह उनके साथ हो जाता है।
यह कहा जाता है कि लॉक को प्राप्त करने और लॉक जारी करने के बीच के समय में एक धागे को आंतरिक लॉक कहा जाता है। जब तक एक धागा एक आंतरिक लॉक का मालिक होता है, कोई भी अन्य धागा एक ही लॉक का अधिग्रहण नहीं कर सकता है। जब वह ताला प्राप्त करने का प्रयास करेगा तो दूसरा धागा अवरुद्ध हो जाएगा।
जब कोई थ्रेड आंतरिक लॉक जारी करता है, तो उस एक्शन और उसी लॉक के किसी भी बाद के अधिग्रहण के बीच एक होने से पहले संबंध स्थापित होता है।
सिंक्रनाइज़ किए जा रहे तरीकों के दो प्रभाव हैं :
सबसे पहले, एक ही वस्तु पर इंटरलेव करने के लिए सिंक्रनाइज़ किए गए तरीकों के दो आह्वान संभव नहीं है।
जब कोई थ्रेड किसी ऑब्जेक्ट के लिए एक सिंक्रोनाइज़ की गई विधि को निष्पादित कर रहा होता है, तो अन्य सभी थ्रेड्स जो ऑब्जेक्ट के साथ पहले थ्रेड को निष्पादित करने तक एक ही ऑब्जेक्ट ब्लॉक (सस्पेंड निष्पादन) के लिए सिंक्रनाइज़ किए गए तरीकों को लागू करते हैं।
दूसरा, जब एक सिंक्रनाइज़ेशन विधि बाहर निकलती है, तो यह स्वचालित रूप से एक ही ऑब्जेक्ट के लिए एक सिंक्रनाइज़ किए गए विधि के किसी भी बाद के आह्वान के साथ एक होने से पहले संबंध स्थापित करता है।
यह गारंटी देता है कि ऑब्जेक्ट की स्थिति में परिवर्तन सभी थ्रेड्स को दिखाई देते हैं।
सिंक्रनाइज़ेशन के अन्य विकल्पों की तलाश करें:
Synchronized normal method
समतुल्य
Synchronized statement
(इसका उपयोग करें)
class A {
public synchronized void methodA() {
// all function code
}
equivalent to
public void methodA() {
synchronized(this) {
// all function code
}
}
}
Synchronized static method
समतुल्य Synchronized statement
(उपयोग वर्ग)
class A {
public static synchronized void methodA() {
// all function code
}
equivalent to
public void methodA() {
synchronized(A.class) {
// all function code
}
}
}
सिंक्रोनाइज़्ड स्टेटमेंट (वेरिएबल का उपयोग करके)
class A {
private Object lock1 = new Object();
public void methodA() {
synchronized(lock1 ) {
// all function code
}
}
}
के लिए synchronized
, हम दोनों Synchronized Methods
और है Synchronized Statements
। हालाँकि, Synchronized Methods
इसके समान Synchronized Statements
ही हमें समझने की आवश्यकता है Synchronized Statements
।
=> मूल रूप से, हमारे पास होगा
synchronized(object or class) { // object/class use to provides the intrinsic lock
// code
}
यहां 2 विचार हैं जो समझने में मदद करते हैं synchronized
intrinsic lock
जुड़ाव होता है।synchronized statement
, तो यह स्वचालित रूप से intrinsic lock
उस synchronized statement's
ऑब्जेक्ट के लिए प्राप्त करता है और विधि के वापस आने पर इसे जारी करता है। जब तक एक धागा का मालिक है intrinsic lock
, कोई अन्य धागा SAME लॉक => थ्रेड सुरक्षित प्राप्त नहीं कर सकता है ।=> जब एक thread A
चालान synchronized(this){// code 1}
=> सभी ब्लॉक कोड (वर्ग के अंदर) जहां है synchronized(this)
और सभी synchronized normal method
(वर्ग के अंदर) लॉक है क्योंकि SAME लॉक है। यह thread A
अनलॉक ("// कोड 1" समाप्त) के बाद निष्पादित होगा ।
यह व्यवहार synchronized(a variable){// code 1}
या के समान है synchronized(class)
।
एक ही ताला => ताला (किस विधि पर निर्भर नहीं है? या कौन सा बयान?)
मैं पसंद करता हूं synchronized statements
क्योंकि यह अधिक विस्तार योग्य है। उदाहरण, भविष्य में, आपको केवल विधि के एक भाग को सिंक्रनाइज़ करने की आवश्यकता है। उदाहरण के लिए, आपके पास 2 सिंक्रनाइज़ विधि है और यह एक दूसरे के लिए प्रासंगिक नहीं है , हालांकि जब कोई थ्रेड विधि चलाता है, तो यह अन्य विधि को ब्लॉक कर देगा (यह उपयोग द्वारा रोका जा सकता है synchronized(a variable)
)।
हालाँकि, सिंक्रोनाइज़ किया हुआ तरीका सरल है और कोड सरल दिखता है। कुछ वर्ग के लिए, एक दूसरे से संबंधित कक्षा में केवल 1 सिंक्रोनाइज़ की गई विधि, या सभी सिंक्रनाइज़ किए गए तरीके => हम synchronized method
कोड को छोटा और समझने में आसान बनाने के लिए उपयोग कर सकते हैं
(यह करने के लिए प्रासंगिक नहीं है synchronized
, यह वस्तु और वर्ग या कोई भी स्थिर और स्थिर के बीच अलग है)।
synchronized
या सामान्य विधि या synchronized(this)
या synchronized(non-static variable)
यह प्रत्येक वस्तु के उदाहरण के आधार पर सिंक्रनाइज़ होगा। synchronized
या स्थिर विधि या synchronized(class)
या synchronized(static variable)
यह वर्ग के आधार पर सिंक्रनाइज़ होगाhttps://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
आशा है कि यह मदद करेगा
यहाँ जावा ट्यूटोरियल से एक स्पष्टीकरण है ।
निम्नलिखित कोड पर विचार करें:
public class SynchronizedCounter { private int c = 0; public synchronized void increment() { c++; } public synchronized void decrement() { c--; } public synchronized int value() { return c; } }
यदि
count
इसका उदाहरण हैSynchronizedCounter
, तो इन विधियों को सिंक्रनाइज़ करने के दो प्रभाव हैं:
- सबसे पहले, एक ही वस्तु पर इंटरलेव करने के लिए सिंक्रनाइज़ किए गए तरीकों के दो आह्वान संभव नहीं है। जब कोई थ्रेड किसी ऑब्जेक्ट के लिए एक सिंक्रोनाइज़ की गई विधि को निष्पादित कर रहा होता है, तो अन्य सभी थ्रेड्स जो ऑब्जेक्ट के साथ पहले थ्रेड को निष्पादित करने तक एक ही ऑब्जेक्ट ब्लॉक (सस्पेंड निष्पादन) के लिए सिंक्रनाइज़ किए गए तरीकों को लागू करते हैं।
- दूसरा, जब एक सिंक्रनाइज़ेशन विधि बाहर निकलती है, तो यह स्वचालित रूप से एक ही ऑब्जेक्ट के लिए एक सिंक्रनाइज़ किए गए विधि के किसी भी बाद के आह्वान के साथ एक होने से पहले संबंध स्थापित करता है। यह गारंटी देता है कि ऑब्जेक्ट की स्थिति में परिवर्तन सभी थ्रेड्स को दिखाई देते हैं।
मेरी समझ के लिए मूल रूप से सिंक्रोनाइज़ करने का मतलब है कि कंपाइलर आपके तरीके के आसपास एक मॉनिटर.इंटरनेट और मॉनिटर.एक्सिट लिखें। जैसे कि यह थ्रेड सुरक्षित हो सकता है कि इसका उपयोग किस प्रकार किया जाता है (मेरा मतलब है कि आप सिंक्रनाइज़ किए गए तरीकों से एक ऑब्जेक्ट लिख सकते हैं जो आपके वर्ग के अनुसार थ्रेडसेफ़ नहीं है)।
अन्य उत्तर गायब हैं एक महत्वपूर्ण पहलू है: मेमोरी बाधाएं । थ्रेड सिंक्रोनाइज़ेशन में मूल रूप से दो भाग होते हैं : क्रमांकन और दृश्यता। मैं हर किसी को "jvm मेमोरी बैरियर" के लिए Google को सलाह देता हूं, क्योंकि यह एक गैर-तुच्छ और अत्यंत महत्वपूर्ण विषय है (यदि आप कई थ्रेड द्वारा एक्सेस किए गए साझा किए गए डेटा को संशोधित करते हैं)। ऐसा करने के बाद, मैं java.util.concurrent पैकेज की कक्षाओं को देखने की सलाह देता हूं जो स्पष्ट सिंक्रनाइज़ेशन का उपयोग करने से बचने में मदद करती हैं, जो बदले में कार्यक्रमों को सरल और कुशल रखने में मदद करती हैं, शायद गतिरोध को भी रोकती हैं।
ऐसा ही एक उदाहरण है, समवर्ती लाईनडेक । कमांड पैटर्न के साथ मिलकर यह समवर्ती कतार में आदेशों को भरकर अत्यधिक कुशल कार्यकर्ता थ्रेड बनाने की अनुमति देता है - कोई स्पष्ट सिंक्रनाइज़ेशन की आवश्यकता नहीं, कोई गतिरोध संभव नहीं, कोई स्पष्ट नींद () आवश्यक नहीं, बस कॉल () ले कर कतार को प्रदूषित करें।
संक्षेप में: "मेमोरी सिंक्रोनाइज़ेशन" तब होता है जब आप एक धागा शुरू करते हैं, एक धागा समाप्त होता है, आप एक अस्थिर चर पढ़ते हैं, आप एक मॉनिटर अनलॉक करते हैं (एक सिंक्रनाइज़ किए गए ब्लॉक / फ़ंक्शन को छोड़ते हैं) आदि यह "सिंक्रनाइज़ेशन" प्रभावित करता है (एक अर्थ में "फ्लश") ") सभी उस विशेष कार्रवाई से पहले किया लिखते हैं। उपरोक्त समवर्ती लिंकनडेक के मामले में , प्रलेखन "कहता है"।
मेमोरी संगति प्रभाव: अन्य समवर्ती संग्रहों के साथ, एक वस्तु में एक वस्तु को रखने से पहले एक थ्रेड में क्रियाएँ एक समवर्तीलिंक में घटित होती हैं , दूसरे सूत्र में उस तत्व की पहुँच या निष्कासन के बाद होने वाली क्रियाओं से पहले ।
यह निहित व्यवहार कुछ हद तक एक खतरनाक पहलू है क्योंकि ज्यादातर जावा प्रोग्रामर बिना ज्यादा अनुभव के सिर्फ इसलिए बहुत कुछ ले लेंगे जैसा कि दिया गया है। और फिर अचानक इस थ्रेड पर ठोकर खाने के बाद जावा ऐसा नहीं कर रहा है जो उत्पादन में ऐसा करने के लिए "माना जाता है" जहां एक अलग कार्य भार है - और यह संगामिति मुद्दों का परीक्षण करना बहुत कठिन है।
सिंक्रोनाइज्ड का सीधा सा मतलब है कि सिंगल थ्रेड से जुड़े कई थ्रेड्स गंदे पढ़ने और लिखने से रोक सकते हैं अगर सिंक्रोनाइज़्ड ब्लॉक का इस्तेमाल किसी खास ऑब्जेक्ट पर किया जाए। आपको और अधिक स्पष्टता प्रदान करने के लिए, एक उदाहरण दें:
class MyRunnable implements Runnable {
int var = 10;
@Override
public void run() {
call();
}
public void call() {
synchronized (this) {
for (int i = 0; i < 4; i++) {
var++;
System.out.println("Current Thread " + Thread.currentThread().getName() + " var value "+var);
}
}
}
}
public class MutlipleThreadsRunnable {
public static void main(String[] args) {
MyRunnable runnable1 = new MyRunnable();
MyRunnable runnable2 = new MyRunnable();
Thread t1 = new Thread(runnable1);
t1.setName("Thread -1");
Thread t2 = new Thread(runnable2);
t2.setName("Thread -2");
Thread t3 = new Thread(runnable1);
t3.setName("Thread -3");
t1.start();
t2.start();
t3.start();
}
}
हमने दो MyRunnable क्लास ऑब्जेक्ट बनाए हैं, runnable1 को थ्रेड 1 के साथ साझा किया जा रहा है और थ्रेड 3 और runnable2 को केवल थ्रेड 2 के साथ साझा किया जा रहा है। अब जब t1 और t3 का उपयोग बिना सिंक्रनाइज़ किए बिना शुरू होता है, तो PFB आउटपुट जो यह बताता है कि थ्रेड 1 और 3 दोनों एक साथ var value को प्रभावित करते हैं जहाँ थ्रेड 2 के लिए, var की अपनी मेमोरी है।
Without Synchronized keyword
Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -2 var value 12
Current Thread Thread -2 var value 13
Current Thread Thread -2 var value 14
Current Thread Thread -1 var value 12
Current Thread Thread -3 var value 13
Current Thread Thread -3 var value 15
Current Thread Thread -1 var value 14
Current Thread Thread -1 var value 17
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 18
Synchronzied का उपयोग करते हुए, थ्रेड 3 सभी स्थितियों में पूर्ण होने के लिए थ्रेड 1 की प्रतीक्षा कर रहा है। अधिग्रहित किए गए दो ताले हैं, एक रननेबल 1 पर थ्रेड 1 और थ्रेड 3 द्वारा साझा किया गया है और दूसरा रननेबल 2 पर थ्रेड 2 द्वारा साझा किया गया है।
Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -1 var value 12
Current Thread Thread -2 var value 12
Current Thread Thread -1 var value 13
Current Thread Thread -2 var value 13
Current Thread Thread -1 var value 14
Current Thread Thread -2 var value 14
Current Thread Thread -3 var value 15
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 17
Current Thread Thread -3 var value 18
सिंक्रोनाइज़्ड सिंपल का मतलब है कि कोई भी दो धागे एक साथ ब्लॉक / मेथड तक नहीं पहुँच सकते। जब हम कहते हैं कि किसी वर्ग का कोई ब्लॉक / विधि सिंक्रनाइज़ है तो इसका मतलब है कि केवल एक धागा उन्हें एक बार में एक्सेस कर सकता है। आंतरिक रूप से जो धागा इसे एक्सेस करने की कोशिश करता है, वह पहले उस ऑब्जेक्ट पर ताला लगाता है और जब तक यह लॉक उपलब्ध नहीं होता है तब तक कोई अन्य धागा क्लास के उस इंस्टेंस के किसी भी तरीके / ब्लॉक को एक्सेस नहीं कर सकता है।
नोट दूसरा थ्रेड उसी ऑब्जेक्ट की विधि तक पहुँच सकता है जिसे सिंक्रनाइज़ नहीं किया गया है। एक थ्रेड लॉक को कॉल करके जारी कर सकता है
Object.wait()
synchronized
जावा में ब्लॉक मल्टीथ्रेडिंग में एक मॉनिटर है। synchronized
एक ही वस्तु / वर्ग के साथ ब्लॉक केवल एक धागे से निष्पादित किया जा सकता है, अन्य सभी इंतजार कर रहे हैं। यह race condition
स्थिति के साथ मदद कर सकता है जब कई धागे एक ही चर को अपडेट करने की कोशिश करते हैं (पहला चरण के बारे में उपयोग कर रहा हैvolatile
)
Java 5
synchronized
समर्थन के द्वारा विस्तारित happens-before
[के बारे में]
किसी मॉनीटर का अनलॉक (सिंक्रोनाइज़्ड ब्लॉक या मेथड एग्जिट) उसी मॉनीटर के हर बाद के लॉक (सिंक्रोनाइज़्ड ब्लॉक या मेथड एंट्री) से पहले होता है।
अगला कदम है java.util.concurrent