MehrdadShirvani a0a2197e71 Merge PR 'Develop' (#1) from develop into main
400 / 500- No Bonus
There were a few issues in the Answers.md file
2026-07-10 16:42:32 +00:00
2026-06-12 00:51:34 +03:30
2026-06-12 00:51:34 +03:30
2026-05-27 17:52:39 +00:00
2026-06-12 21:10:49 +03:30
2026-06-05 23:02:45 +03:30

Ninth Assignment — Advanced Multithreading

HW09 Image.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:

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:

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)

S
Description
No description provided
Readme
1.3 MiB
Languages
Java 100%