Java synchronized keyword example

Maggie 43 Published: 12/12/2024

Java synchronized keyword example

The synchronized keyword is a fundamental concept in Java that allows multiple threads to share the same resource safely. It's used to ensure that only one thread can access a specific block of code at a time, preventing conflicts and ensuring data consistency.

Let's dive into an example:

Suppose we have a simple banking system with multiple users accessing their accounts simultaneously. Each user wants to withdraw money from their account, but we need to ensure that the withdrawal process is atomic, meaning it either succeeds or fails entirely. We can achieve this using the synchronized keyword.

Here's the code:

class BankAccount {

private int balance;

public BankAccount(int initialBalance) {

balance = initialBalance;

}

public synchronized void withdraw(int amount) {

if (amount > 0 && balance >= amount) {

balance -= amount;

System.out.println("Withdrawal successful! New balance: " + balance);

} else {

System.out.println("Insufficient funds or invalid withdrawal amount.");

}

}

}

class UserThread extends Thread {

private BankAccount account;

private int amount;

public UserThread(BankAccount account, int amount) {

this.account = account;

this.amount = amount;

}

@Override

public void run() {

try {

Thread.sleep((int) (Math.random() * 1000)); // Simulate some delay

} catch (InterruptedException e) {

// Handle the exception

}

account.withdraw(amount);

}

}

public class SynchronizedExample {

public static void main(String[] args) {

BankAccount account = new BankAccount(1000); // Initial balance is java000

UserThread t1 = new UserThread(account, 200);

UserThread t2 = new UserThread(account, 300);

UserThread t3 = new UserThread(account, 400);

t1.start();

t2.start();

t3.start();

// Wait for all threads to finish

try {

Thread.sleep((int) (Math.random() * 2000)); // Simulate some delay

} catch (InterruptedException e) {

// Handle the exception

}

}

}

In this example, we have a BankAccount class with a withdraw method that is synchronized. This means that only one thread can execute this method at a time.

We then create multiple user threads (UserThread) that withdraw money from the account. Each thread simulates some delay before withdrawing the funds. The synchronized keyword ensures that only one withdrawal operation can be executed at a time, preventing conflicts and ensuring data consistency.

When you run the program, you'll see that each withdrawal operation is atomic and doesn't interfere with other threads' actions. This is because the synchronized method ensures that only one thread can access the critical section of code (i.e., the withdrawal logic) at a time.

In this example, we've demonstrated how the synchronized keyword can be used to ensure thread safety in Java. This is just one of many scenarios where synchronization plays a crucial role in ensuring data consistency and preventing conflicts between multiple threads.

How to write synchronization in Java?

I'm happy to help, but I'll make sure to respond in English as per your request.

Synchronization is a crucial concept in Java programming that helps ensure the consistency and integrity of shared resources in multithreaded environments. In this response, we will explore how to write synchronization in Java using various mechanisms.

1. Synchronized Methods

One way to achieve synchronization is by declaring a method as synchronized. This ensures that only one thread can execute the method at a time. Here's an example:

public class SynchronizedExample {

public synchronized void doSomething() {

// Code to be executed

}

}

When a thread calls the doSomething() method, it will acquire the lock on the object before executing the code inside the method. If another thread tries to call the same method simultaneously, it will have to wait until the first thread finishes executing.

2. Locks

Java provides several built-in locks that can be used for synchronization purposes:

ReentrantLock: This is a more advanced lock that allows a thread to acquire and release the lock multiple times. Lock: This is a basic lock that can be used for simple synchronization needs. ReadWriteLock: This is a specialized lock designed for situations where you need to read or write shared resources.

Here's an example using the ReentrantLock class:

import java.util.concurrent.locks.ReentrantLock;

public class LockExample {

private ReentrantLock lock = new ReentrantLock();

public void doSomething() {

lock.lock();

try {

// Code to be executed

} finally {

lock.unlock();

}

}

}

3. Atomic Variables

Java provides atomic variables that can be used for synchronization purposes. These variables are designed to work with the volatile keyword, which ensures that changes made by one thread are visible to other threads.

Here's an example:

public class AtomicExample {

private volatile int counter = 0;

public void incrementCounter() {

counter++;

}

}

4. Semaphores

Java provides a Semaphore class that can be used for synchronization purposes. A semaphore is a variable that controls the access to shared resources.

Here's an example:

import java.util.concurrent.Semaphore;

public class SemaphoreExample {

private final Semaphore semaphore = new Semaphore(1);

public void doSomething() {

try {

semaphore.acquire();

// Code to be executed

} finally {

semaphore.release();

}

}

}

5. Concurrent Collections

Java provides several concurrent collections that can be used for synchronization purposes. These collections are designed to work with multiple threads simultaneously.

Here's an example using the ConcurrentHashMap class:

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {

private final ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

public void doSomething() {

map.put("key", 1);

}

}

In conclusion, Java provides several mechanisms for writing synchronization code. By choosing the right mechanism for your specific needs, you can ensure that your multithreaded programs are efficient and scalable.