What is thread-safe in Java with real time example?

Martin 92 Published: 09/13/2024

What is thread-safe in Java with real time example?

In Java, a thread-safe program ensures that the data accessed by multiple threads remains consistent and valid throughout the execution of the program. Thread safety is critical when working with multithreaded applications to prevent errors like data corruption or inconsistent results.

A thread-safe method in Java is one that can be safely executed by multiple threads concurrently without causing unexpected behavior, such as incorrect calculations or memory leaks.

Here's a real-time example to illustrate this concept:

Example: A simple banking system that allows multiple customers to deposit and withdraw money simultaneously from their accounts.

Consider two methods: withdraw() and deposit(), which are called by multiple customer threads to update their account balances. These methods should be thread-safe to ensure the integrity of the account data.

Thread-unsafe code:

public class BankAccount {

private double balance;

public void withdraw(double amount) {

balance -= amount;

}

public void deposit(double amount) {

balance += amount;

}

}

In this example, if multiple customer threads simultaneously call withdraw() or deposit(), the program may produce incorrect results. For instance:

Customer A withdraws $100, and just as the transaction is being processed, Customer B withdraws $50.

The final balance might be $50 instead of $50 (A's initial balance minus 100) + 50 (B's withdrawal), causing an inconsistent state.

Thread-safe code:

public class BankAccount {

private double balance;

private final Object lock = new Object();

public void withdraw(double amount) {

synchronized (lock) {

balance -= amount;

}

}

public void deposit(double amount) {

synchronized (lock) {

balance += amount;

}

}

}

By using the synchronized keyword and locking on a shared object (lock) for both withdraw() and deposit(), we ensure that these methods are thread-safe. This means that only one thread can execute either method at a time, preventing concurrent updates to the account balance.

How it works:

When multiple threads attempt to access the same method (e.g., withdraw()), they will compete for the lock. The first thread to acquire the lock will execute its operation and then release the lock. Other threads waiting for the lock will be blocked until the lock is released, ensuring that only one thread can modify the account balance at a time.

In conclusion, making methods thread-safe in Java ensures that your program behaves predictably when multiple threads access shared resources simultaneously. By using synchronization primitives like synchronized and locking objects, you can create thread-safe code that prevents data corruption and ensures consistent results.

what is thread-safe java

I'll respond in English.

In Java, a program is said to be "thread-safe" when it can operate correctly and safely in the presence of multiple threads concurrently executing the same code. In other words, a thread-safe program ensures that the data shared among different threads remains consistent, and no unexpected behavior or errors occur due to concurrent access or modification.

To achieve thread safety in Java, you need to consider the following best practices:

Synchronize Access to Shared Resources: Ensure that all accesses to shared resources (e.g., variables, collections, files) are properly synchronized using Java's built-in synchronization mechanisms, such as synchronized methods and locks. Use Immutable Objects or Clone Them: If an object is immutable (i.e., its state cannot be changed after construction), multiple threads can safely access it concurrently. Alternatively, you can clone the object to create a new copy for each thread. Avoid Shared State: Try to minimize shared state by using independent copies of data or encapsulating state within individual threads. This approach reduces the need for synchronization and minimizes potential concurrency issues. Use Atomic Variables or Locks: When updating shared variables, use Atomic classes (like AtomicInteger) or locks to ensure thread safety. These classes provide atomic operations that can be safely executed by multiple threads concurrently. Carefully Use Static Variables: Static variables are shared among all instances of a class. If not properly synchronized, they can introduce concurrency issues. Consider using instance-specific variables instead. Avoid Nested Locks: When acquiring locks, try to avoid nested lock acquisitions, as this can lead to deadlocks or livelocks. Instead, use ReentrantLock with timeouts and retry mechanisms to handle such scenarios. Use Thread-Local Storage: In some cases, you might need to maintain thread-specific data. Use ThreadLocal variables for this purpose. Test Your Code: Finally, thoroughly test your code under concurrent execution scenarios to ensure that it behaves as expected.

In summary, achieving thread safety in Java requires careful consideration of the best practices outlined above. By following these guidelines, you can write programs that operate correctly and safely in the presence of multiple threads concurrently executing the same code.