The synchronized
keyword in Java is used to control access to critical sections of code by multiple threads. It ensures that only one thread can execute a block of code or method at a time, preventing race conditions and ensuring thread safety.
Table of Contents
- Introduction
synchronized
Keyword Syntax- Understanding
synchronized
- Examples
- Synchronized Method
- Synchronized Block
- Static Synchronized Method
- Real-World Use Case
- Conclusion
Introduction
In multithreaded programming, it is essential to ensure that shared resources are accessed in a thread-safe manner. The synchronized
keyword provides a way to achieve this by locking the resource or code block, ensuring that only one thread can access it at a time.
synchronized Keyword Syntax
Synchronized Method:
public synchronized void methodName() { // method body }
Synchronized Block:
public void methodName() { synchronized (this) { // synchronized code block } }
Understanding synchronized
Key Points:
- Synchronized Method: Locks the entire method, allowing only one thread to execute it at a time.
- Synchronized Block: Locks a specific block of code within a method, providing finer control over synchronization.
- Static Synchronized Method: Locks the class itself, ensuring that only one thread can execute any static synchronized method of the class at a time.
Examples
Synchronized Method
A method that is synchronized to ensure thread safety.
Example
public class Counter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } public static void main(String[] args) { Counter counter = new Counter(); Runnable task = () -> { for (int i = 0; i < 1000; i++) { counter.increment(); } }; Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Final count: " + counter.getCount()); } }
Output:
Final count: 2000
Synchronized Block
A block of code within a method that is synchronized.
Example
public class Counter { private int count = 0; public void increment() { synchronized (this) { count++; } } public int getCount() { return count; } public static void main(String[] args) { Counter counter = new Counter(); Runnable task = () -> { for (int i = 0; i < 1000; i++) { counter.increment(); } }; Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Final count: " + counter.getCount()); } }
Output:
Final count: 2000
Static Synchronized Method
A static method that is synchronized to ensure thread safety at the class level.
Example
public class Counter { private static int count = 0; public static synchronized void increment() { count++; } public static int getCount() { return count; } public static void main(String[] args) { Runnable task = () -> { for (int i = 0; i < 1000; i++) { Counter.increment(); } }; Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Final count: " + Counter.getCount()); } }
Output:
Final count: 2000
Real-World Use Case
Bank Account Example
In real-world applications, the synchronized
keyword is often used to ensure the thread safety of operations that modify shared resources, such as bank account balances.
Example
public class BankAccount { private double balance; public BankAccount(double initialBalance) { this.balance = initialBalance; } public synchronized void deposit(double amount) { balance += amount; } public synchronized void withdraw(double amount) { if (balance >= amount) { balance -= amount; } else { System.out.println("Insufficient funds"); } } public double getBalance() { return balance; } public static void main(String[] args) { BankAccount account = new BankAccount(1000); Runnable depositTask = () -> { for (int i = 0; i < 100; i++) { account.deposit(10); } }; Runnable withdrawTask = () -> { for (int i = 0; i < 100; i++) { account.withdraw(10); } }; Thread depositThread = new Thread(depositTask); Thread withdrawThread = new Thread(withdrawTask); depositThread.start(); withdrawThread.start(); try { depositThread.join(); withdrawThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Final balance: " + account.getBalance()); } }
Output:
Final balance: 1000.0
Conclusion
The synchronized
keyword in Java is used for ensuring thread safety in concurrent programming. By using synchronized
methods and blocks, you can prevent race conditions and ensure that shared resources are accessed in a controlled and safe manner. Understanding and using the synchronized
keyword effectively is crucial for writing robust and reliable multithreaded Java applications.