Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c9eec7bf7 | ||
|
|
80a0bc794a |
Generated
+10
@@ -0,0 +1,10 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Ignored default folder with query files
|
||||
/queries/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
Generated
+13
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="HW-09-Advanced-Multithreading" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+20
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://mirror-maven.runflare.com/maven2" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+12
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="23" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
### Atomic Variables & Synchronization
|
||||
|
||||
---
|
||||
|
||||
**1 -**
|
||||
|
||||
These kinds of variables make single variables lock-free and safe to use multiple threads.
|
||||
|
||||
Atomic variables solve the problem of thread-safe updates to shared variables without using explicit synchronization.
|
||||
|
||||
Ordinary ones may not be seen by other threads but atomic variables are immediately visible to other threads. Threads can interleave between operations like increment and cause Race Condition.
|
||||
|
||||
**2 -**
|
||||
|
||||
`AtomicInteger`, `AtomicLong`, `AtomicBoolean`, `AtomicIntegerArray`
|
||||
|
||||
For example, the most common use case for `AtomicBoolean` is ensuring that a particular action or initialization routine executes exactly once in a multi-threaded environment, even when multiple threads attempt to trigger it simultaneously.
|
||||
|
||||
**3 -**
|
||||
|
||||
An atomic variable is better for one variable, one operation and Locks are better in multiple variables or multiple steps:
|
||||
|
||||
Single counter increment >>> Atomic variable
|
||||
|
||||
Long-running update operation >>> Lock
|
||||
|
||||
### Locks & Concurrent Design
|
||||
|
||||
---
|
||||
|
||||
**4 -**
|
||||
|
||||
Under high contention, even correctly synchronized code can degrade severely due to how threads coordinate access to shared resources.
|
||||
|
||||
Three concurrency-related factors that can be mentioned are: Lock Contention (Serialization), Cache Coherency Traffic, Oversubscription and Context Switching
|
||||
|
||||
**5 -**
|
||||
|
||||
Adding more threads increases context switching overhead as the OS spends more time saving and restoring thread states than doing actual work. Higher contention for shared resources (locks, atomic variables) causes threads to serialize and wait, while cache coherence traffic forces CPUs to constantly invalidate and reload shared data. These factors create a point of diminishing returns where additional threads reduce throughput instead of improving it.
|
||||
|
||||
### Deadlocks
|
||||
|
||||
---
|
||||
|
||||
**6 -**
|
||||
|
||||
Deadlocks are rare timing-dependent bugs. Testing environments are too controlled (fewer threads, slower execution, predictable scheduling) to trigger the precise lock interleaving required. Production's chaos—more threads, faster speeds, random OS scheduling—makes that rare timing much more likely to happen.
|
||||
|
||||
Strategy 1: Use a controlled randomizer for thread scheduling. Inject small, random delays (`Thread.sleep()` or `yield()`) at strategic points between lock acquisitions.
|
||||
|
||||
Strategy 2: Run tests with aggressive oversubscription. Test with significantly more threads than CPU cores.
|
||||
@@ -1,9 +1,13 @@
|
||||
package dev.banking.model;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class BankAccount {
|
||||
|
||||
private final int accountId;
|
||||
private long balance;
|
||||
private Lock lock = new ReentrantLock();
|
||||
|
||||
/*
|
||||
* Students may introduce additional fields
|
||||
@@ -32,7 +36,13 @@ public class BankAccount {
|
||||
* - Should not block unnecessarily if using read/write locks
|
||||
*/
|
||||
public long getBalance() {
|
||||
throw new UnsupportedOperationException("TODO: implement thread-safe balance read");
|
||||
// throw new UnsupportedOperationException("TODO: implement thread-safe balance read");
|
||||
try {
|
||||
lock.lock();
|
||||
return this.balance;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -43,7 +53,13 @@ public class BankAccount {
|
||||
* - Must not lose updates under concurrency
|
||||
*/
|
||||
public void deposit(long amount) {
|
||||
throw new UnsupportedOperationException("TODO: implement thread-safe deposit");
|
||||
// throw new UnsupportedOperationException("TODO: implement thread-safe deposit");
|
||||
try {
|
||||
lock.lock();
|
||||
this.balance += amount;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -56,7 +72,13 @@ public class BankAccount {
|
||||
* to extend the system (optional)
|
||||
*/
|
||||
public void withdraw(long amount) {
|
||||
throw new UnsupportedOperationException("TODO: implement thread-safe withdraw");
|
||||
// throw new UnsupportedOperationException("TODO: implement thread-safe withdraw");
|
||||
try {
|
||||
lock.lock();
|
||||
this.balance -= amount;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -73,6 +95,29 @@ public class BankAccount {
|
||||
* - Or tryLock with retry strategy
|
||||
*/
|
||||
public void transfer(BankAccount target, long amount) {
|
||||
throw new UnsupportedOperationException("TODO: implement atomic deadlock-free transfer");
|
||||
|
||||
if (this.accountId < target.accountId) {
|
||||
this.lock.lock();
|
||||
target.lock.lock();
|
||||
} else if (this == target) {
|
||||
return;
|
||||
} else {
|
||||
target.lock.lock();
|
||||
this.lock.lock();
|
||||
}
|
||||
|
||||
try {
|
||||
this.withdraw(amount);
|
||||
target.deposit(amount);
|
||||
} finally {
|
||||
if (this.accountId < target.accountId) {
|
||||
target.lock.unlock();
|
||||
this.lock.unlock();
|
||||
} else {
|
||||
this.lock.unlock();
|
||||
target.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user