Java synchronized Keyword

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

  1. Introduction
  2. synchronized Keyword Syntax
  3. Understanding synchronized
  4. Examples
    • Synchronized Method
    • Synchronized Block
    • Static Synchronized Method
  5. Real-World Use Case
  6. 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.

Leave a Comment

Scroll to Top