Difference between revisions of "Atomicity"

From CSE231 Wiki
Jump to navigation Jump to search
Line 56: Line 56:
  
 
=Code To Fix=
 
=Code To Fix=
: ''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!''
+
For this part of the studio we are presented with broken code. Despite using a thread-safe concurrent map:
  
{{CodeToImplement|StockPortfolio|transfer|atomicity.stockportfolio.studio}}
+
<nowiki>private final ConcurrentMap<String, Integer> map;</nowiki>
  
<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

Motivation

Many race conditions can be prevented by proper encapsulation avoiding check-then-write and read-then-modify-then-write in non-atomically.

Background

Concurrency Tutorial

Synchronized Methods
Intrinsic Locks

ConcurrentMap

compute

Code To Investigate

YUCK

class: CheckThenActCourse.java DEMO: Java.png
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 Java.png
methods: addIfSpace
drop
package: atomicity.course.studio
source folder: student/src/main/java

method: public boolean addIfSpace(Student student) Sequential.svg (sequential implementation only)

method: public boolean drop(Student student) Sequential.svg (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 Java.png
methods: transfer
package: atomicity.stockportfolio.studio
source folder: student/src/main/java

Testing Your Solution

Correctness

class: AtomicityTestSuite.java Junit.png
package: atomicity
source folder: testing/src/test/java