319 lines
7.2 KiB
Markdown
319 lines
7.2 KiB
Markdown
# HW-09 — Advanced Multithreading
|
|
|
|
---
|
|
## 📋 Introduction
|
|
This assignment is divided into two main sections:
|
|
|
|
### **Theoretical Questions**:
|
|
- You are asked to answer questions about multithreading concepts.
|
|
|
|
### **Practical Project**:
|
|
- You are asked to implement a banking system that performs concurrent operations using multithreading. The main goal of the exercise is handling deadlocks and race conditions so that the program performs correctly.
|
|
|
|
---
|
|
|
|
## 🧠 Theoretical Questions
|
|
|
|
### **Note**:
|
|
**Write your answers in a Markdown file (e.g. Answers.md) and place it in the root directory of your forked repository.**
|
|
|
|
### ⚛️ Atomic Variables & Synchronization
|
|
|
|
---
|
|
|
|
**1 -** What are atomic variables?
|
|
|
|
Explain their purpose and how they differ from ordinary (non-atomic) variables.
|
|
|
|
**2 -** Name at least four classes from the `java.util.concurrent.atomic` package that provide atomic operations for different data types.
|
|
|
|
For one of them, briefly describe a typical use case.
|
|
|
|
**3 -** Compare locks with atomic variables.
|
|
|
|
In which scenarios is using a lock a better choice than an atomic variable, and vice versa?
|
|
|
|
#### 🎯Bonus Task:
|
|
|
|
Write a small Java program that concurrently increments a normal int variable and an AtomicInteger variable from multiple threads. Print the final values of both variables to demonstrate that the atomic variable produces the correct result, while the normal variable may show an inconsistent value due to a race condition.
|
|
|
|
### 🔒 Locks & Concurrent Design
|
|
|
|
---
|
|
|
|
**4 -** A program is completely free of race conditions but still performs poorly under high contention.
|
|
|
|
Explain how this situation can occur.
|
|
|
|
Discuss at least three concurrency-related factors that may limit scalability even when correctness is guaranteed.
|
|
|
|
**5 -** Many concurrent systems experience performance degradation as the number of threads increases.
|
|
|
|
Explain why adding more threads does not always improve performance.
|
|
|
|
Your answer should discuss concepts such as:
|
|
|
|
Context switching
|
|
Contention
|
|
Cache coherence
|
|
Synchronization overhead
|
|
|
|
### ⚠️ Deadlocks
|
|
|
|
---
|
|
|
|
**6 -** Deadlocks often only appear in production, not during testing.
|
|
|
|
Explain why this might happen from a thread-scheduling perspective.
|
|
|
|
Describe two strategies a developer can use to increase the likelihood of exposing deadlocks during testing.
|
|
|
|
---
|
|
## 💻 Practical Project
|
|
|
|
## 🏦 Advanced Banking & Transaction Processing System
|
|
|
|
---
|
|
|
|
### 🧭 Overview
|
|
|
|
Modern banking systems process thousands of transactions concurrently. Multiple worker threads may read account data, update balances, or transfer money between accounts simultaneously.
|
|
|
|
In this assignment, you will implement the **concurrency control layer** of a banking system. The goal is to ensure:
|
|
|
|
* Correctness under concurrent execution
|
|
* Absence of race conditions
|
|
* Deadlock-free transfers
|
|
* Reasonable concurrency performance
|
|
|
|
---
|
|
|
|
### 📦 Provided Components (IMPORTANT)
|
|
|
|
The following parts of the system are already implemented and **must NOT be modified**:
|
|
|
|
#### ✅ Fully implemented:
|
|
|
|
* Transaction stream parsing
|
|
* Transaction generation / loading
|
|
* ExecutorService (thread pool) setup
|
|
* Worker thread management
|
|
* System startup and execution flow
|
|
* Live monitoring / balance visualization
|
|
* JUnit test suite
|
|
|
|
---
|
|
|
|
### ❗ Your Responsibility
|
|
|
|
You are ONLY responsible for implementing thread-safe logic inside:
|
|
|
|
#### 📄 `BankAccount.java`
|
|
|
|
You must implement the following methods:
|
|
|
|
```java
|
|
deposit(int amount);
|
|
withdraw(int amount);
|
|
transfer(BankAccount target, int amount);
|
|
getBalance();
|
|
```
|
|
|
|
---
|
|
|
|
### 🏗 System Architecture
|
|
|
|
```
|
|
Transaction Stream
|
|
│
|
|
▼
|
|
ExecutorService Pool
|
|
│
|
|
┌──────────────────┼──────────────────┐
|
|
▼ ▼ ▼
|
|
Worker A Worker B Worker C
|
|
│ │ │
|
|
└──────────────────┼──────────────────┘
|
|
▼
|
|
Shared Bank Accounts
|
|
```
|
|
|
|
Multiple worker threads may access the same accounts concurrently.
|
|
|
|
Execution order is **non-deterministic**, and correctness must be guaranteed regardless of scheduling.
|
|
|
|
---
|
|
|
|
### 🧠 Core Requirement
|
|
|
|
Your implementation must ensure:
|
|
|
|
* Shared state consistency
|
|
* Thread safety
|
|
* No lost updates
|
|
* Correct final balances regardless of thread execution order
|
|
|
|
---
|
|
|
|
## 🛠 Implementation Requirements
|
|
|
|
---
|
|
|
|
### 🟢 Phase 1 — Thread-Safe Account Operations
|
|
|
|
Implement safe concurrent access for:
|
|
|
|
* deposit
|
|
* withdraw
|
|
* getBalance
|
|
|
|
#### Requirements:
|
|
|
|
* No lost updates
|
|
* No corrupted balances
|
|
* Multiple threads may safely access different accounts concurrently
|
|
* `getBalance()` must always return a valid state
|
|
|
|
---
|
|
|
|
### 🔵 Phase 2 — Atomic Transfers
|
|
|
|
Implement:
|
|
|
|
```java
|
|
transfer(BankAccount target, int amount);
|
|
```
|
|
|
|
#### Requirements:
|
|
|
|
* Transfer must be **atomic**
|
|
* Money must never be created or lost
|
|
* Partial updates are NOT allowed
|
|
* Concurrent transfers must not corrupt balances
|
|
|
|
Example of invalid behavior:
|
|
|
|
```
|
|
A → B transfer starts
|
|
A is debited
|
|
Crash / thread switch happens
|
|
B is never credited ❌
|
|
```
|
|
|
|
---
|
|
|
|
### 🔴 Phase 3 — Deadlock Prevention
|
|
|
|
Transfers involve TWO accounts, which introduces risk of deadlock.
|
|
|
|
Example:
|
|
|
|
```
|
|
Thread 1: A → B
|
|
Thread 2: B → A
|
|
```
|
|
|
|
If locks are acquired incorrectly, the system may freeze.
|
|
|
|
#### Requirements:
|
|
|
|
* System must be completely deadlock-free
|
|
* Must pass stress tests with high concurrency
|
|
* Must work under arbitrary transaction ordering
|
|
|
|
---
|
|
|
|
### ⚙ Allowed Java Concurrency Tools
|
|
|
|
You may use:
|
|
|
|
* `synchronized`
|
|
* `ReentrantLock`
|
|
* `ReentrantReadWriteLock`
|
|
* `Condition`
|
|
* `Atomic classes`
|
|
* `java.util.concurrent` utilities
|
|
|
|
---
|
|
|
|
### ❌ Not Allowed
|
|
|
|
* Busy waiting (e.g., `while(true)`)
|
|
* Modifying test files
|
|
* Modifying method signatures
|
|
* Creating additional worker threads
|
|
* Changing system architecture outside `BankAccount`
|
|
|
|
---
|
|
|
|
### 📊 Live Monitoring (Debug Tool)
|
|
|
|
The system includes a live balance visualization tool.
|
|
|
|
It shows:
|
|
|
|
* Real-time account balances
|
|
* Effects of concurrent transactions
|
|
* Potential race conditions
|
|
|
|
⚠ This tool is NOT part of grading.
|
|
|
|
---
|
|
|
|
### 🧪 Testing
|
|
|
|
A full JUnit test suite is provided.
|
|
|
|
Your solution will be evaluated on:
|
|
|
|
---
|
|
|
|
#### ✅ Correctness
|
|
|
|
* No race conditions
|
|
* No lost updates
|
|
* Correct final balances
|
|
|
|
---
|
|
|
|
#### 🧨 Robustness
|
|
|
|
* No deadlocks under stress tests
|
|
* Stable execution under high concurrency
|
|
* Correct behavior under random transaction ordering
|
|
|
|
---
|
|
|
|
#### ⚡ Performance
|
|
|
|
* Independent accounts should not block each other unnecessarily
|
|
* Avoid global locking unless absolutely necessary
|
|
* System should scale with number of threads
|
|
|
|
---
|
|
|
|
### 🌟 Bonus Challenge (Optional)
|
|
|
|
Implement conditional waiting for insufficient funds:
|
|
|
|
* Withdraw should wait if balance is insufficient
|
|
* Transfer should wait until funds are available
|
|
|
|
#### Requirements:
|
|
|
|
* No busy waiting
|
|
* No CPU spinning
|
|
* No starvation
|
|
|
|
---
|
|
|
|
### 💡 Hint
|
|
|
|
Start with correctness first.
|
|
|
|
Then optimize concurrency.
|
|
|
|
A simple correct solution is always better than a fast incorrect one.
|
|
|
|
|