Synchronized Java भाषा में एक अंतर्निहित सिंक्रनाइज़ेशन तंत्र है जो कोड के क्रिटिकल सेक्शन तक अनन्य पहुँच प्रदान करता है। Oracle, 2024 के अनुसार, synchronized मॉडिफ़ायर गारंटी देता है कि केवल एक थ्रेड ही चिह्नित विधि या ब्लॉक को एक विशिष्ट समय पर निष्पादित कर सकता है। यह तंत्र मॉनिटर्स पर आधारित है — ऑपरेटिंग सिस्टम की एक मौलिक अवधारणा जो सभी जटिलता स्तरों के मल्टीथ्रेडेड अनुप्रयोगों के सही संचालन को सुनिश्चित करती है।
मुख्य बिंदु
Synchronized Java में एक कीवर्ड है जो गारंटी देता है कि किसी भी समय केवल एक थ्रेड कोड के एक संरक्षित अनुभाग को निष्पादित करता है, समवर्ती पहुँच के दौरान डेटा भ्रष्टाचार को रोकता है। यह Java के पहले संस्करण में दिखाई दिया और किसी भी स्तर के डेवलपर्स के लिए थ्रेड सुरक्षा सुनिश्चित करने का सबसे सरल तरीका बना हुआ है।
Synchronized मॉडिफ़ायर दो कार्यों को हल करता है: परस्पर बहिष्करण (mutual exclusion) और परिवर्तनों की दृश्यता (visibility)। जब कोई थ्रेड synchronized ब्लॉक से बाहर निकलता है, तो सभी परिवर्तन उन अन्य थ्रेड्स को दिखाई देते हैं जो उसी ऑब्जेक्ट पर सिंक्रनाइज़ ब्लॉक में प्रवेश करते हैं।
Synchronized को एक पूरी विधि पर या मॉनिटर ऑब्जेक्ट निर्दिष्ट करके किसी कोड ब्लॉक पर लागू किया जा सकता है। दोनों मामलों में, JVM बाइटकोड स्तर पर monitorenter और monitorexit निर्देश डालता है।
सिंक्रनाइज़ेशन के बिना मल्टीथ्रेडेड अनुप्रयोगों में, रेस कंडीशन (race condition) उत्पन्न होती है — जब दो थ्रेड एक साथ समान डेटा को संशोधित करते हैं, जिससे अप्रत्याशित परिणाम होते हैं। Synchronized इस समस्या से निपटने के लिए Java का पहला और प्रमुख उपकरण बन गया, जो किसी भी डेवलपर के लिए सुलभ एक सरल घोषणात्मक सिंटैक्स प्रदान करता है।
Synchronized तंत्र मॉनिटर की अवधारणा पर आधारित है — एक उच्च-स्तरीय सिंक्रनाइज़ेशन प्रिमिटिव जो प्रत्येक Java ऑब्जेक्ट में निर्मित है। मॉनिटर किसी ऑब्जेक्ट से तब जुड़ता है जब पहली बार उस पर synchronized ब्लॉक का उपयोग किया जाता है।
Java में प्रत्येक ऑब्जेक्ट से एक संबद्ध मॉनिटर होता है। जब कोई थ्रेड synchronized ब्लॉक में प्रवेश करता है, तो वह ऑब्जेक्ट के मॉनिटर को प्राप्त करता है। यदि मॉनिटर पहले से किसी अन्य थ्रेड द्वारा धारित है, तो थ्रेड तब तक ब्लॉक हो जाता है जब तक वह मुक्त न हो। बाइटकोड में, यह monitorenter और monitorexit निर्देशों की जोड़ी से मेल खाता है।
JVM कई स्तरों के माध्यम से synchronized को अनुकूलित करता है: एकल-थ्रेड पहुँच के लिए biased locking (पक्षपाती लॉकिंग), कम प्रतिस्पर्धा के लिए lightweight locking (हल्का लॉकिंग), और OS भागीदारी के साथ तीव्र प्रतिस्पर्धा के लिए heavyweight locking (भारी लॉकिंग)। ये स्तर कोड को बदले बिना प्रदर्शन में सुधार करते हैं।
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
Synchronized एक happens-before संबंध स्थापित करता है: synchronized ब्लॉक से बाहर निकलने से पहले एक थ्रेड में सभी क्रियाएँ उसी ऑब्जेक्ट पर सिंक्रनाइज़ ब्लॉक में प्रवेश करने के बाद दूसरे थ्रेड को दिखाई देती हैं। यह न केवल परस्पर बहिष्करण बल्कि सभी थ्रेड्स के लिए डेटा संगति भी सुनिश्चित करता है।
Java synchronized को लागू करने के दो तरीके प्रदान करता है: विधि स्तर पर और ब्लॉक स्तर पर। उनके बीच चयन प्रदर्शन और सिंक्रनाइज़ेशन ग्रैन्युलैरिटी को प्रभावित करता है।
synchronized मॉडिफ़ायर के साथ विधि को चिह्नित करना स्वचालित रूप से इसे वर्तमान इंस्टेंस (सामान्य विधि के लिए) या Class ऑब्जेक्ट (स्थैतिक विधि के लिए) पर सिंक्रनाइज़ करता है। यह परस्पर बहिष्करण सुनिश्चित करने का सबसे सरल तरीका है, लेकिन यह अक्सर अत्यधिक होता है यदि क्रिटिकल सेक्शन विधि का केवल एक छोटा हिस्सा है और शेष कोड को सिंक्रनाइज़ेशन की आवश्यकता नहीं है।
Synchronized ब्लॉक सटीक नियंत्रण देता है: आप मॉनिटर ऑब्जेक्ट निर्दिष्ट करते हैं और कोड के केवल आवश्यक भाग को सिंक्रनाइज़ करते हैं, शेष विधि को लॉक के बाहर छोड़ते हैं। यह मॉनिटर धारण समय को कम करता है और मल्टीथ्रेडेड वातावरण में समग्र एप्लिकेशन प्रदर्शन में सुधार करता है, क्योंकि अन्य थ्रेड्स मॉनिटर के जारी होने की प्रतीक्षा किए बिना समानांतर रूप से असंबंधित कोड निष्पादित कर सकते हैं।
class DataProcessor {
private final Object lock = new Object();
public void process() {
// क्रिटिकल सेक्शन के बाहर कोड - बिना सिंक्रनाइज़ेशन
prepareData()
synchronized (lock) {
// केवल यह ब्लॉक सुरक्षित है
updateSharedState()
}
// बिना लॉक के जारी
cleanup()
}
}
| मानदंड | Synchronized विधि | Synchronized ब्लॉक |
|---|---|---|
| मॉनिटर | this (इंस्टेंस) या Class | कोई भी ऑब्जेक्ट |
| ग्रैन्युलैरिटी | पूरी विधि | केवल आवश्यक कोड |
| पठनीयता | उच्च | मध्यम |
| प्रदर्शन | बड़ी विधियों के लिए कम | छोटे क्रिटिकल सेक्शन के लिए अधिक |
Android विकास में, synchronized का व्यापक रूप से SharedPreferences, डेटाबेस एक्सेस और UI घटकों की सुरक्षा के लिए उपयोग किया जाता है। हालाँकि, मुख्य थ्रेड पर इसका उपयोग इंटरफ़ेस फ़्रीज़िंग के जोखिम के कारण सख्ती से अनुशंसित नहीं है।
Android में SharedPreferences बुनियादी थ्रेड सुरक्षा प्रदान करता है, लेकिन Editor के माध्यम से कई थ्रेड्स से संपादन करते समय बाहरी सिंक्रनाइज़ेशन की आवश्यकता हो सकती है। एक अलग लॉक ऑब्जेक्ट के साथ synchronized ब्लॉक परिवर्तनों की संगति सुनिश्चित करता है।
class PreferencesManager(private val prefs: SharedPreferences) {
private val lock = Any()
fun writeToken(token: String) {
synchronized (lock) {
prefs.edit()
.putString("auth_token", token)
.apply()
}
}
}
Android पर synchronized की मुख्य सीमा थ्रेड ब्लॉकिंग है। Mutex के साथ coroutines के विपरीत, synchronized सिस्टम थ्रेड को पूरी तरह से ब्लॉक करता है। मुख्य थ्रेड पर, यह ANR का कारण बनता है। आधुनिक Android विकास में, synchronized को coroutines (suspend Mutex) या परमाणु प्रकारों (AtomicInteger) से बदलने की अनुशंसा की जाती है।
आधुनिक Java और Kotlin synchronized के कई विकल्प प्रदान करते हैं, प्रत्येक समान समस्याओं को कम सीमाओं या बेहतर प्रदर्शन के साथ हल करता है।
Lock इंटरफ़ेस ReentrantLock और ReadWriteLock कार्यान्वयन के साथ टाइमआउट, बाधित प्रतीक्षा और कई Condition कतारें प्रदान करता है। यह synchronized से अधिक लचीला है लेकिन finally में स्पष्ट रिलीज़ की आवश्यकता होती है, जो unlock भूल जाने पर त्रुटि का जोखिम बढ़ाता है।
AtomicInteger, AtomicLong, AtomicReference और अन्य वर्ग CAS (Compare-And-Swap) पर आधारित Lock-Free एल्गोरिदम का उपयोग करते हैं। वे मध्यम प्रतिस्पर्धा वाले परिदृश्यों में synchronized से काफी तेज़ हैं क्योंकि वे थ्रेड्स को ब्लॉक नहीं करते बल्कि OS कर्नेल संदर्भ स्विचिंग की आवश्यकता के बिना आशावादी पुनः प्रयास करते हैं।
ThreadLocal एक वैकल्पिक दृष्टिकोण प्रदान करता है: प्रत्येक ThreadLocal चर एक थ्रेड के भीतर पृथक होता है और पढ़ने और लिखने के लिए सिंक्रनाइज़ेशन की आवश्यकता नहीं होती है। यह उन डेटा के लिए synchronized की आवश्यकता को पूरी तरह से समाप्त कर देता है जो थ्रेड्स के बीच साझा नहीं होने चाहिए। ThreadLocal का उपयोग फ्रेमवर्क (Spring, Hibernate) में लेन-देन संदर्भ और सत्रों को संग्रहीत करने के लिए सक्रिय रूप से किया जाता है।
Android के लिए Kotlin प्रोजेक्ट्स में, synchronized का विकल्प kotlinx.coroutines से Mutex है। यह ऑपरेटिंग सिस्टम थ्रेड को ब्लॉक नहीं करता बल्कि लॉक जारी होने तक coroutine को निलंबित करता है — यह पूल थ्रेड्स के कुशल उपयोग और संसाधन जारी होने की लंबी प्रतीक्षा के दौरान ANR से बचने की अनुमति देता है।
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
val mutex = Mutex()
var counter = 0
suspend fun safeIncrement() {
mutex.withLock {
counter++
}
}
Synchronized का प्रदर्शन हाल के Java संस्करणों में काफी बदल गया है। पहले इसे “भारी” तंत्र माना जाता था, लेकिन आधुनिक JVM ने उन्नत JIT कंपाइलर ऑप्टिमाइज़ेशन के माध्यम से अधिकांश ओवरहेड को समाप्त कर दिया है। आइए विस्तार से देखें कि वर्चुअल मशीन रनटाइम पर सिंक्रनाइज़ कोड को कैसे तेज़ करती है।
JVM JIT कंपाइलर कई ऑप्टिमाइज़ेशन लागू करता है: biased locking सिंक्रनाइज़ेशन को समाप्त करता है यदि लॉक हमेशा उसी थ्रेड द्वारा प्राप्त किया जाता है; lock coarsening आसन्न synchronized ब्लॉकों को एक में मर्ज करता है; lock elimination सिंक्रनाइज़ेशन को हटा देता है यदि ऑब्जेक्ट केवल एक थ्रेड द्वारा सुलभ है। ये ऑप्टिमाइज़ेशन कम प्रतिस्पर्धा पर synchronized को वस्तुतः मुफ्त बनाते हैं।
JVM प्रत्येक ऑब्जेक्ट के लिए प्रतिस्पर्धा स्तर निर्धारित करता है: जब कोई प्रतिस्पर्धा नहीं होती है, तो biased locking सक्षम होता है; जब दूसरा थ्रेड प्रकट होता है, तो लॉक स्पिन-प्रतीक्षा के साथ lightweight मोड में परिवर्तित होता है; और केवल लंबी प्रतीक्षा के दौरान यह सिस्टम म्यूटेक्स के साथ heavyweight में परिवर्तित होता है। यह परिवर्तन स्वचालित रूप से होता है, और डेवलपर को मैन्युअल रूप से रणनीति चुनने की आवश्यकता नहीं होती है।
आधुनिक बेंचमार्क (Java 17+) में, synchronized कम और मध्यम प्रतिस्पर्धा पर ReentrantLock के बराबर प्रदर्शन दिखाता है। उच्च प्रतिस्पर्धा पर, Lock को टाइमआउट और इंटरप्ट समर्थन के साथ अधिक कुशल प्रतीक्षा कतार के कारण लाभ हो सकता है। उच्च-लोड सिस्टम के लिए जहाँ प्रतिस्पर्धा स्थिर है, fair मोड के साथ ReentrantLock अधिक पूर्वानुमानित व्यवहार प्रदान करता है।
परमाणु वर्ग (AtomicInteger, AtomicReference) CAS पर Lock-Free कार्यान्वयन के कारण सरल काउंटर और फ़्लैग के लिए सबसे तेज़ बने हुए हैं। वे थ्रेड्स को बिल्कुल भी ब्लॉक नहीं करते — संघर्ष पर, ऑपरेशन बस एक लूप में पुनः प्रयास करता है। यह 4-8 थ्रेड्स के साथ काउंटर वृद्धि संचालन पर synchronized की तुलना में 3-5 गुना प्रदर्शन लाभ देता है।
अक्सर पूछे जाने वाले प्रश्न
Synchronized परस्पर बहिष्करण और दृश्यता दोनों प्रदान करता है। Volatile केवल परिवर्तनों की दृश्यता की गारंटी देता है — volatile चर में लिखना सभी थ्रेड्स को दिखाई देता है लेकिन एक साथ संशोधन को नहीं रोकता, अर्थात यह रेस कंडीशन से रक्षा नहीं करता।
हाँ, deadlock विभिन्न मॉनिटर क्रम के साथ नेस्टेड सिंक्रनाइज़ेशन में संभव है। उदाहरण के लिए, एक थ्रेड synchronized(a) { synchronized(b) } कहता है, जबकि दूसरा synchronized(b) { synchronized(a) } कहता है। नेस्टेड synchronized ब्लॉक से बचें या एक सुसंगत मॉनिटर क्रम निर्धारित करें।
मॉनिटर एक सिंक्रनाइज़ेशन तंत्र है जो प्रत्येक Java ऑब्जेक्ट से जुड़ा होता है। यह गारंटी देता है कि केवल एक थ्रेड उस ऑब्जेक्ट पर synchronized कोड निष्पादित करता है। मॉनिटर में एक लॉक, एक प्रतीक्षा कतार और wait/notify के माध्यम से सूचना की प्रतीक्षा करने वाले थ्रेड्स का एक पूल शामिल है।
आधुनिक Java संस्करणों (17+) में, synchronized JIT ऑप्टिमाइज़ेशन (biased locking, lock coarsening) के कारण प्रदर्शन में Lock से पीछे नहीं है। Lock को गति के लिए नहीं बल्कि अतिरिक्त क्षमताओं के लिए प्राथमिकता दी जाती है: टाइमआउट, बाधित प्रतीक्षा और कई Condition कतारें।
स्टैटिक synchronized विधि दिए गए वर्ग के Class ऑब्जेक्ट के मॉनिटर का उपयोग करती है, न कि इंस्टेंस का। इसका अर्थ है कि सिंक्रनाइज़ेशन वर्ग के सभी इंस्टेंस पर लागू होता है। गैर-स्टैटिक और स्टैटिक synchronized विधियाँ विभिन्न मॉनिटर का उपयोग करती हैं और एक दूसरे को ब्लॉक नहीं करती हैं।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें