Java में Synchronization
In this page:
synchronized returnType methodName() {
// one thread at a time
}
synchronized (lockObject) {
// critical section
}
What is Synchronization?
Synchronization वह mechanism है जो Java कई threads के shared resources तक access को control करने के लिए प्रदान करता है, race conditions, data corruption, और सूक्ष्म memory-visibility bugs को रोकते हुए। इसके बिना, एक ही variable को एक साथ पढ़ने और लिखने वाले दो threads ऐसे results पैदा कर सकते हैं जो किसी भी thread का अकेले इरादा नहीं था।
उदाहरण: What is Synchronization?
public class Main {
static int counter = 0;
public static void main(String[] args) throws InterruptedException {
Runnable increment = () -> { for (int i = 0; i < 1000; i++) counter++; };
Thread t1 = new Thread(increment);
Thread t2 = new Thread(increment);
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println(counter); // may be less than 2000 without synchronization
}
}
Login to try C/C++/Java/PHP code in the editor
Synchronized Methods
किसी method की declaration में synchronized keyword जोड़कर, आप access को इस तरह सीमित करते हैं कि किसी दिए गए object instance पर एक समय में सिर्फ एक thread वह method execute कर सके। कोई भी दूसरा thread जो इसे call करने की कोशिश करे उसे पहले thread के method से बाहर निकलने तक इंतज़ार करना होगा, चाहे सामान्य रूप से हो या किसी exception के ज़रिए।
उदाहरण: Synchronized Methods
public class Main {
static class Counter {
private int count = 0;
synchronized void increment() { count++; }
int getCount() { return count; }
}
public static void main(String[] args) throws InterruptedException {
Counter c = new Counter();
Runnable task = () -> { for (int i = 0; i < 1000; i++) c.increment(); };
Thread t1 = new Thread(task), t2 = new Thread(task);
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println(c.getCount()); // reliably 2000
}
}
Login to try C/C++/Java/PHP code in the editor
Synchronized Blocks
पूरे method को synchronize करना एक performance bottleneck बना सकता है अगर ज़्यादातर method का काम असल में shared state को छूता ही नहीं। Synchronized blocks आपको सिर्फ उन specific lines को lock करने देते हैं जिन्हें सुरक्षा चाहिए, critical section को छोटा करते हुए और यह घटाते हुए कि दूसरे threads को कितना इंतज़ार करना पड़े।
उदाहरण: Synchronized Blocks
// Define the class Main
public class Main {
static int total = 0;
// Create a new Object object and store it in lock
static final Object lock = new Object();
// Program entry point: the JVM starts running here
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
// Loop: repeat while the condition holds
for (int i = 0; i < 1000; i++) {
// synchronized lets only one thread run this code at a time
synchronized (lock) { total++; }
}
};
// Create a new Thread object and store it in t1
Thread t1 = new Thread(task), t2 = new Thread(task);
// Start the thread; it runs in parallel with this code
t1.start(); t2.start();
// Wait for the thread to finish
t1.join(); t2.join();
System.out.println(total);
}
}
Login to try C/C++/Java/PHP code in the editor
Static Synchronization
अगर आप किसी static method को synchronized declare करें, तो पाया गया lock किसी individual instance के बजाय खुद Class object पर होता है। यही असल में हर instance में share किए गए static, class-level variables की सुरक्षा करता है, क्योंकि instance-level locks उन्हें cover नहीं करते।
उदाहरण: Static Synchronization
public class Main {
static int sharedCount = 0;
static synchronized void increment() { // locks the Class object, not an instance
sharedCount++;
}
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> { for (int i = 0; i < 1000; i++) increment(); };
Thread t1 = new Thread(task), t2 = new Thread(task);
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println(sharedCount);
}
}
Login to try C/C++/Java/PHP code in the editor
Understanding Deadlocks
एक deadlock तब होता है जब दो या ज़्यादा threads स्थायी रूप से block हो जाते हैं, हर एक किसी ऐसे lock का इंतज़ार कर रहा हो जो कोई दूसरा blocked thread रखता है, इसलिए कोई भी कभी आगे नहीं बढ़ पाता। अपने पूरे codebase में locks को एक consistent, predictable order में पाना, और जहां संभव हो nested synchronized blocks से बचना, इसे रोकने का standard तरीका है।
उदाहरण: Understanding Deadlocks
public class Main {
static final Object lockA = new Object();
static final Object lockB = new Object();
public static void main(String[] args) {
// Acquiring locks in a consistent order (lockA then lockB) avoids deadlock
synchronized (lockA) {
synchronized (lockB) {
System.out.println("Both locks acquired safely, in order");
}
}
}
}
Login to try C/C++/Java/PHP code in the editor
- यह मान लेना कि
counter++atomic है, जबकि यह पढ़ना, जोड़ना और लिखना है, इसलिए दो threads बिनाsynchronizedया किसी atomic class के updates खो सकते हैं। - अलग-अलग threads में अलग-अलग objects पर synchronize करना, जैसे
synchronized (new Object()), जिससे कोई lock असल में share नहीं होता और कुछ भी सुरक्षित नहीं होता। - अलग-अलग threads में दो objects को अलग order में lock करना, जो एक deadlock का कारण बन सकता है जहां हर thread हमेशा के लिए दूसरे के lock का इंतज़ार करता है।
Chapter Quiz — Complete all 8 topics to unlock
0/8 topics done
Complete these topics first: