# Ninth Assignment — Advanced Multithreading

![HW09 Image.png](HW09%20Image.png)

---
## 📋 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 & Concurrent Transaction System

---

### 🧭 Overview

In modern banking systems, thousands of transactions are processed concurrently by multiple worker threads. These threads may access shared bank accounts simultaneously, leading to potential race conditions and consistency issues.

In this assignment, you will implement the **core concurrency control layer** of a banking simulation system.

Your goal is to ensure:

* Correctness under concurrent execution
* consistent account state under concurrent execution
* Deadlock-free transfer operations
* Reasonable concurrency and scalability

Students are expected to design their own synchronization strategy from scratch.

---

### 📦 Provided System (DO NOT MODIFY)

The following components are fully implemented and must not be changed:

#### ✅ Infrastructure Layer

* Transaction generation and models
* TransactionProcessor (dispatch layer)
* BankingSystem (task submission layer)
* ExecutorService configuration
* Worker thread execution model
* DemoApplication (system runner)
* Live monitoring (debug tool)
* JUnit test suite

---

### ❗ Your Responsibility (IMPORTANT)

You are ONLY responsible for implementing thread-safe logic inside:

#### 📄 `BankAccount.java`

You must implement:

```java
deposit(long amount);
withdraw(long amount);
transfer(BankAccount target, long amount);
getBalance();
```

Additionally, you may introduce internal synchronization design choices such as:

* Locks
* ReadWriteLock
* Atomic variables
* Custom ordering strategies

---

### 🏗 System Architecture

```
              Transaction Stream
                       │
                       ▼
            TransactionProcessor
                       │
                       ▼
            BankingSystem (task submission via ExecutorService)
                       │
        ┌──────────────┼──────────────┐
        ▼              ▼              ▼
    Worker A       Worker B       Worker C
        │              │              │
        └──────────────┼──────────────┘
                       ▼
                Shared Bank Accounts
```

Multiple worker threads may operate on the same account simultaneously.

Execution order is **non-deterministic**, and correctness must hold for all possible schedules.

---

### 🧠 Core Design Requirement

Your solution must guarantee:

* No race conditions
* No lost updates
* Atomic multi-step operations
* Deadlock-free execution under all conditions

---

## 🛠 Implementation Phases

---

### 🟢 Phase 1 — Thread-Safe Account State

Implement safe access and mutation for account balance:

#### Methods:

* `getBalance()`
* `deposit()`
* `withdraw()`

#### Requirements:

* No race conditions
* Reads must never observe invalid intermediate state
* Multiple accounts must remain independently concurrent
* Negative balances are allowed unless explicitly handled by your implementation.

---

### 🔵 Phase 2 — Atomic Transfers

Implement:

```java
transfer(BankAccount target, long amount);
```

#### Requirements:

* Transfer must be **fully atomic**
* No partial updates allowed
* Money must never be lost or created
* Consistency must hold under concurrent transfers

#### Important:

A transfer involves **two shared resources (accounts)**, which introduces synchronization complexity beyond simple locking.

---

### 🔴 Phase 3 — Deadlock-Free Design

Concurrent transfers may create cyclic locking scenarios:

```
Thread 1: A → B
Thread 2: B → A
```

#### Requirements:

* System must be completely deadlock-free
* Must pass high-concurrency stress tests
* Must remain correct under arbitrary execution ordering

---

### ⚙ Allowed Concurrency Tools

You may use:

* `synchronized`
* `ReentrantLock`
* `ReentrantReadWriteLock`
* `Condition`
* `Atomic classes`
* `java.util.concurrent` utilities

---

### ❌ Restrictions

You are NOT allowed to:

* Use busy waiting (e.g., `while(true)`)
* Modify test files
* Modify method signatures
* Change system architecture outside `BankAccount`
* Create additional worker threads
* Modify transaction processing pipeline

---

### 📊 Live Monitoring (Debug Support)

A monitoring system is included to display real-time account balances.

It helps you:

* Observe race conditions
* Debug concurrency issues
* Validate correctness under load

⚠ This component is NOT part of grading and may produce non-deterministic output.

---

### 🧪 Testing

A full JUnit test suite validates your solution.

Your implementation 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 unpredictable scheduling

---

#### ⚡ Performance

* Independent accounts should not block each other
* Avoid unnecessary global locking
* Maintain scalable concurrency

---

### 🌟 Bonus Challenge (Optional)

Implement **conditional waiting for insufficient funds**:

* `withdraw()` waits until balance is sufficient
* `transfer()` waits until source has enough funds

#### Requirements:

* No busy waiting
* No CPU spinning
* No starvation
* Must remain thread-safe

⚠ **Note on Bonus:** The provided JUnit test suite assumes the base behavior (allowing balances to proceed without waiting). Implementing the bonus challenge might cause some base stress tests to time out due to threads waiting indefinitely for funds. It is recommended to verify the bonus logic using your own custom test scenarios.

---

### 💡 Final Hint

> A correct solution is always more valuable than an optimized incorrect one.

Start simple, ensure correctness, then improve concurrency and performance.

---

## Submission ⌛

1. Add your mentor as a collaborator or reviewer on the repository.
2. Create a `develop` branch (from `main`) for implementing features.
3. Use Git for regular commits with meaningful commit messages.
4. Push your code and the answers file (Answers.md) to the remote repository.
5. Submit a pull request to merge the `develop` branch into `main`.

**Deadline:** Friday, June 12 (22nd of Khordad)