← Back to Advanced Java Course | Chapter 2: Multithreading | Lesson 4 of 8

Java में Synchronization

Synchronization threads को किसी shared चीज़ का उपयोग करने के लिए बारी-बारी करने पर मजबूर करता है, जैसे दरवाज़े पर lock लगा एक अकेला bathroom। यह उन्हें एक-दूसरे का काम बिगाड़ने से रोकता है।
Syntax
java
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?

java
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
	}
}

Synchronized Methods

किसी method की declaration में synchronized keyword जोड़कर, आप access को इस तरह सीमित करते हैं कि किसी दिए गए object instance पर एक समय में सिर्फ एक thread वह method execute कर सके। कोई भी दूसरा thread जो इसे call करने की कोशिश करे उसे पहले thread के method से बाहर निकलने तक इंतज़ार करना होगा, चाहे सामान्य रूप से हो या किसी exception के ज़रिए।

उदाहरण: Synchronized Methods

java
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
	}
}

Synchronized Blocks

पूरे method को synchronize करना एक performance bottleneck बना सकता है अगर ज़्यादातर method का काम असल में shared state को छूता ही नहीं। Synchronized blocks आपको सिर्फ उन specific lines को lock करने देते हैं जिन्हें सुरक्षा चाहिए, critical section को छोटा करते हुए और यह घटाते हुए कि दूसरे threads को कितना इंतज़ार करना पड़े।

उदाहरण: Synchronized Blocks

java
// 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);
	}
}

Static Synchronization

अगर आप किसी static method को synchronized declare करें, तो पाया गया lock किसी individual instance के बजाय खुद Class object पर होता है। यही असल में हर instance में share किए गए static, class-level variables की सुरक्षा करता है, क्योंकि instance-level locks उन्हें cover नहीं करते।

उदाहरण: Static Synchronization

java
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);
	}
}

Understanding Deadlocks

एक deadlock तब होता है जब दो या ज़्यादा threads स्थायी रूप से block हो जाते हैं, हर एक किसी ऐसे lock का इंतज़ार कर रहा हो जो कोई दूसरा blocked thread रखता है, इसलिए कोई भी कभी आगे नहीं बढ़ पाता। अपने पूरे codebase में locks को एक consistent, predictable order में पाना, और जहां संभव हो nested synchronized blocks से बचना, इसे रोकने का standard तरीका है।

उदाहरण: Understanding Deadlocks

java
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");
			}
		}
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. यह मान लेना कि counter++ atomic है, जबकि यह पढ़ना, जोड़ना और लिखना है, इसलिए दो threads बिना synchronized या किसी atomic class के updates खो सकते हैं।
  2. अलग-अलग threads में अलग-अलग objects पर synchronize करना, जैसे synchronized (new Object()), जिससे कोई lock असल में share नहीं होता और कुछ भी सुरक्षित नहीं होता।
  3. अलग-अलग threads में दो objects को अलग order में lock करना, जो एक deadlock का कारण बन सकता है जहां हर thread हमेशा के लिए दूसरे के lock का इंतज़ार करता है।

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.