0% found this document useful (0 votes)
4 views2 pages

Java Multi-threaded Bank Account Example

The document contains a Java implementation of a thread-safe BankAccount class using ReentrantLock for managing deposits and withdrawals. It demonstrates concurrent access to the account by creating 100 threads, with 50 depositing and 50 withdrawing amounts. The final balance and execution time for all threads are printed after completion.

Uploaded by

Taspia Tabassum
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views2 pages

Java Multi-threaded Bank Account Example

The document contains a Java implementation of a thread-safe BankAccount class using ReentrantLock for managing deposits and withdrawals. It demonstrates concurrent access to the account by creating 100 threads, with 50 depositing and 50 withdrawing amounts. The final balance and execution time for all threads are printed after completion.

Uploaded by

Taspia Tabassum
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

import [Link].

Lock;
import [Link];
class BankAccount {
private double balance;
private final Lock lock = new ReentrantLock();

public BankAccount(double initialBalance) {


[Link] = initialBalance;
}

public void deposit(double amount) {


[Link]();
try {
balance += amount;
[Link]("Deposited: " + amount);
} finally {
[Link]();
}
}

public void withdraw(double amount) {


[Link]();
try {
if (balance >= amount) {
balance -= amount;
[Link]("Withdrawn: " + amount);
} else {
[Link]("Insufficient funds for withdrawal.");
}
} finally {
[Link]();
}
}

public double getBalance() {


return balance;
}
}

public class BankAccountDemoMT {


public static void main(String[] args) {
BankAccount account = new BankAccount(1000.0);

long startTime = [Link]();


Thread[] allThreads = new Thread[100];
for (int i = 0; i < 100; i++) {
allThreads[i] = i < 50 ? new Thread(() -> [Link](100.0)) : new Thread(() ->
[Link](15.0));
allThreads[i].start();
}

for (Thread thread : allThreads) {


try {
[Link]();
} catch (InterruptedException e) {
[Link]();
}
}

long endTime = [Link]();


[Link]("All threads completed in " + (endTime - startTime) + " milliseconds");
[Link]("Final balance: " + [Link]());
}
}

Common questions

Powered by AI

The fixed number of deposit and withdrawal threads in the BankAccountDemoMT class balances the transaction types, simulating a balanced inflow and outflow scenario. This design allows for a controlled environment to test and observe the system's behavior under concurrent transactions. It is significant because it helps ensure the lock mechanism effectively manages access while preventing any bias towards deposits or withdrawals, maintaining a predictable final balance under correct operation. This setup helps evaluate how the system handles contention and ensures operational integrity across a typical financial operation mix.

If the thread joining process is omitted, the main thread might terminate before all deposit and withdrawal operations are completed, leading to a premature evaluation of the final account balance and execution time. This could result in incorrect data being printed or processed, as some threads would still be executing or might not have been scheduled to run yet. Using join ensures that the main thread waits for all threads to finish, allowing for accurate and reliable final output reflecting the intended concurrent operations.

The current implementation of the BankAccount class might face issues such as performance bottlenecks due to contention, where many threads are competing for the lock, leading to increased waiting times. Deadlocks can occur if improperly handled, though it's not an immediate issue here. To mitigate these problems, using finer-grained locking strategies or lock-free algorithms could be beneficial. Additionally, implementing a fair lock policy using ReentrantLock's fairness setting or optimizing the logic to reduce lock holding time might mitigate performance issues. Also, considering thread pool management may help handle thread overload efficiently.

The use of ReentrantLock in the BankAccount class ensures thread safety by protecting the critical sections of the deposit and withdraw methods. When a thread calls the lock method, it gains exclusive access to execute the code within the try block. This prevents other threads from entering these sections simultaneously, thereby avoiding race conditions and ensuring data consistency. The unlock method is invoked in the finally block to release the lock, allowing other threads to proceed. This manner of locking ensures that only one thread can modify the balance at a time, maintaining data integrity during concurrent transactions.

Using a try-finally block within the deposit and withdraw methods improves reliability by ensuring that the lock is consistently released after the critical section is executed. This pattern ensures that resources are properly managed, regardless of whether an exception occurs, thereby preventing resource leakage or deadlock. As such, the system remains robust and capable of handling concurrency safely, which is critical in multithreaded programming where exception scenarios can otherwise lead to blocking issues.

Placing the lock.unlock() call inside a finally block is important because it ensures that the lock is always released, even if an exception is thrown during the execution of the critical section. This prevents deadlock scenarios where other threads remain forever blocked, unable to acquire the lock. By ensuring that the lock is released in all circumstances, the system maintains its ability to handle subsequent requests correctly, thus ensuring proper functioning and reliability.

If unlock was called before the completion of the deposit and withdraw operations, the critical section would no longer be protected, allowing multiple threads to access and modify the balance simultaneously. This would lead to race conditions, where simultaneous updates could cause inconsistent data states, resulting in incorrect final balances that do not accurately reflect the net of operations. Such behavior would undermine the integrity of concurrent operations and could lead to unpredictable and erroneous system outputs, highlighting the necessity of maintaining lock protection until operations are fully completed.

The multi-threading in the BankAccountDemoMT program exemplifies concurrency control's essential role in financial systems by simulating simultaneous deposit and withdrawal operations, akin to real-life banking transactions. Concurrency control is crucial to preventing race conditions, ensuring data consistency, and maintaining transactional integrity across parallel operations. Through the use of locks, the program ensures that operations are atomic and isolated, reflecting real-world needs to handle multiple client transactions correctly without data corruption or inconsistencies, which are critical in ensuring system reliability and user trust.

Increasing the number of deposit and withdrawal threads can potentially increase the execution time due to greater contention for the ReentrantLock, resulting in threads spending more time waiting to acquire the lock. Furthermore, unless carefully balanced, the final account balance may become unpredictable due to the timing and order of operations. However, since deposit and withdrawal amounts are fixed, with appropriate locking, the expected final balance should ideally align with the net of deposits made and withdrawals, assuming no overdrafts occur.

Replacing ReentrantLock with ReadWriteLock can improve concurrency by allowing multiple threads to read the balance simultaneously, as read locks are shared. However, since deposits and withdrawals are write operations needing exclusive access, the actual impact on concurrency for this scenario may be minimal, given the need to frequently update the balance. As a result, using ReadWriteLock might not offer significant benefits over ReentrantLock in this specific case, where read operations are not predominant. Therefore, it might not be particularly suitable unless the application is read-heavy.

You might also like