Assignment-9
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
### 1. Atomic Variables & Synchronization
|
||||
#### What are atomic variables and what are they used for?
|
||||
- Atomic variables are specialized variables that handle updates in a single, uninterruptible step.
|
||||
They allow multiple threads to work on the same data safely without needing to use manual locks.
|
||||
|
||||
#### Name at least four classes from the java.util.concurrent.atomic package that provide atomic operations for different data types, and briefly describe a typical use case for one of them.
|
||||
- Four common classes from the package are:
|
||||
```
|
||||
AtomicInteger (for int values)
|
||||
|
||||
AtomicLong (for long values)
|
||||
|
||||
AtomicBoolean (for boolean values)
|
||||
|
||||
AtomicReference (for object references)
|
||||
```
|
||||
For example, `AtomicInteger` is usually used for high-performance counters that need to be updated by multiple threads simultaneously.
|
||||
|
||||
#### Compare locks with atomic variables. Explain where each one is usually used.
|
||||
- Atomic variables are usually used when we just need to update a single variable or a flag since they're faster and simpler.
|
||||
But locks are usually used when dealing with multiple dependent variables or complex logic and conditions.
|
||||
|
||||
---
|
||||
### 2. Locks & Concurrent Design
|
||||
#### Explain why a program could be completely free of race conditions but still perform poorly under high contention. Discuss at least three concurrency-related factors that may limit scalability even when correctness is guaranteed.
|
||||
- Correctness doesn't always mean scalability.
|
||||
1. Coarse-Grained Locking: Locking a large section of code instead of just the piece you need.
|
||||
2. Lock Contention: Having too many threads fighting to grab the exact same lock at the exact same time.
|
||||
3. Thread Orchestration Overhead: The Operating System using significant CPU power just to "manage" threads (switching, waking, and pausing) rather than actually running the code.
|
||||
|
||||
#### Explain why adding more threads does not always improve performance. Discuss what concepts like Context switching, Contention, Cache coherence, and Synchronization overhead mean.
|
||||
- Having too many threads does not necessarily mean better performance.
|
||||
1. Context switching: Changing from thread A to thread B requires saving and loading thread states,
|
||||
Which spends CPU power.
|
||||
2. Contention: More threads mean more competition for limited resources, which leads to threads spending their time waiting for locks to release instead of processing data.
|
||||
3. Cache coherence: When cores share data, they have to constantly sync their local caches. This interaction between CPU cores slows everything down.
|
||||
4. Synchronization overhead: Acquiring and releasing locks require extra CPU instructions. If the code uses too many locks, the CPU spends all its time checking safety protocols instead of doing the actual work.
|
||||
|
||||
---
|
||||
### 3. Deadlocks
|
||||
#### Explain why Deadlocks often only appear in production, not during testing from a thread-scheduling perspective.
|
||||
- Deadlocks are timing-dependent. They only occur when threads interleave in a very specific, rare order that often doesn’t happen under light testing loads.
|
||||
|
||||
#### Describe two strategies a developer can use to increase the likelihood of exposing deadlocks during testing.
|
||||
- We can use some strategies, such as:
|
||||
1. High-Concurrency Stress Testing: Using a large number of threads performing random operations simultaneously to trigger high-concurrency scenarios that might not happen with just 2–3 threads.
|
||||
2. Injecting Artificial Timing Delays: Adding a random `Thread.sleep(10)` before acquiring and releasing locks or during other high stress moments. This forces the threads to encounter non-deterministic execution paths which makes timing-based bugs much easier to spot.
|
||||
Reference in New Issue
Block a user