Difference between revisions of "Atomicity"
Jump to navigation
Jump to search
Line 56: | Line 56: | ||
=Code To Fix= | =Code To Fix= | ||
− | + | For this part of the studio we are presented with broken code. Despite using a thread-safe concurrent map: | |
− | + | <nowiki>private final ConcurrentMap<String, Integer> map;</nowiki> | |
− | + | it suffers from an atomicity race: | |
<nowiki>private int transfer(String listingSymbol, int deltaShareCount) { | <nowiki>private int transfer(String listingSymbol, int deltaShareCount) { | ||
Line 73: | Line 73: | ||
return newValue; | return newValue; | ||
}</nowiki> | }</nowiki> | ||
+ | |||
+ | Recalling the song: | ||
+ | |||
+ | : ''get then put is not atomic<br>call [https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#compute-K-java.util.function.BiFunction- compute]<br>call [https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#compute-K-java.util.function.BiFunction- compute]<br>use [https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html ConcurrentHashMap]<br>use [https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html ConcurrentHashMap]<br>or say shoot!<br>or say shoot!'' | ||
+ | |||
+ | fix this code. | ||
+ | |||
+ | {{CodeToImplement|StockPortfolio|transfer|atomicity.stockportfolio.studio}} | ||
=Testing Your Solution= | =Testing Your Solution= | ||
==Correctness== | ==Correctness== | ||
{{TestSuite|AtomicityTestSuite|atomicity}} | {{TestSuite|AtomicityTestSuite|atomicity}} |
Revision as of 21:29, 12 April 2018
Contents
Motivation
Many race conditions can be prevented by proper encapsulation avoiding check-then-write and read-then-modify-then-write in non-atomically.
Background
Code To Investigate
YUCK
class: | CheckThenActCourse.java | DEMO: |
methods: | isSpaceRemaining add drop |
|
package: | atomicity.course.studio | |
source folder: | src//java |
public class CheckThenActCourse { private final Collection<Student> students; private final int limit; public CheckThenActCourse(int limit, Supplier<Collection<Student>> collectionSupplier) { this.students = collectionSupplier.get(); this.limit = limit; } public int getLimit() { return this.limit; } public boolean isSpaceRemaining() { synchronized (this.students) { return this.students.size() < this.limit; } } public void add(Student student) { synchronized (this.students) { this.students.add(student); } } public boolean drop(Student student) { synchronized (this.students) { return this.students.remove(student); } } }
Code To Implement
class: | Course.java | |
methods: | addIfSpace drop |
|
package: | atomicity.course.studio | |
source folder: | student/src/main/java |
method: public boolean addIfSpace(Student student)
(sequential implementation only)
method: public boolean drop(Student student)
(sequential implementation only)
Code To Fix
For this part of the studio we are presented with broken code. Despite using a thread-safe concurrent map:
private final ConcurrentMap<String, Integer> map;
it suffers from an atomicity race:
private int transfer(String listingSymbol, int deltaShareCount) { Integer oldValue = this.map.get(listingSymbol); Integer newValue; if (oldValue != null) { newValue = oldValue + deltaShareCount; } else { newValue = deltaShareCount; } this.map.put(listingSymbol, newValue); return newValue; }
Recalling the song:
- get then put is not atomic
call compute
call compute
use ConcurrentHashMap
use ConcurrentHashMap
or say shoot!
or say shoot!
fix this code.
class: | StockPortfolio.java | |
methods: | transfer | |
package: | atomicity.stockportfolio.studio | |
source folder: | student/src/main/java |
Testing Your Solution
Correctness
class: | AtomicityTestSuite.java | |
package: | atomicity | |
source folder: | testing/src/test/java |