New/improved synchronization examples
This commit is contained in:
parent
551389ccd0
commit
a05aa3e445
27
concurrent/SynchronizedConstructor.java
Normal file
27
concurrent/SynchronizedConstructor.java
Normal file
@ -0,0 +1,27 @@
|
||||
// concurrent/SynchronizedConstructor.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
import java.util.concurrent.atomic.*;
|
||||
|
||||
class SyncConstructor implements HasID {
|
||||
private final int id;
|
||||
private static Object constructorLock = new Object();
|
||||
public SyncConstructor(SharedArg sa) {
|
||||
synchronized(constructorLock) {
|
||||
id = sa.get();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int getID() { return id; }
|
||||
}
|
||||
|
||||
public class SynchronizedConstructor {
|
||||
public static void main(String[] args) {
|
||||
Unsafe unsafe = new Unsafe();
|
||||
IDChecker.test(() -> new SyncConstructor(unsafe));
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
0
|
||||
*/
|
@ -7,28 +7,14 @@ import java.util.concurrent.atomic.*;
|
||||
import java.util.*;
|
||||
import onjava.*;
|
||||
|
||||
public class AtomicIntegerTest implements Runnable {
|
||||
public class AtomicIntegerTest extends IntTestable {
|
||||
private AtomicInteger i = new AtomicInteger(0);
|
||||
public int getValue() { return i.get(); }
|
||||
private void evenIncrement() { i.addAndGet(2); }
|
||||
@Override
|
||||
public void run() {
|
||||
while(true)
|
||||
evenIncrement();
|
||||
}
|
||||
public int getAsInt() { return i.get(); }
|
||||
public void evenIncrement() { i.addAndGet(2); }
|
||||
public static void main(String[] args) {
|
||||
new TimedAbort(4, "No failures discovered");
|
||||
AtomicIntegerTest ait = new AtomicIntegerTest();
|
||||
CompletableFuture.runAsync(ait);
|
||||
while(true) {
|
||||
int val = ait.getValue();
|
||||
if(val % 2 != 0) {
|
||||
System.out.println(val);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
Atomicity.test(new AtomicIntegerTest());
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
No failures discovered
|
||||
No failures found
|
||||
*/
|
||||
|
21
lowlevel/AtomicSerialNumbers.java
Normal file
21
lowlevel/AtomicSerialNumbers.java
Normal file
@ -0,0 +1,21 @@
|
||||
// lowlevel/AtomicSerialNumbers.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
import java.util.concurrent.atomic.*;
|
||||
|
||||
public class
|
||||
AtomicSerialNumbers extends SerialNumbers {
|
||||
private AtomicInteger serialNumber =
|
||||
new AtomicInteger();
|
||||
public synchronized int nextSerialNumber() {
|
||||
return serialNumber.getAndIncrement();
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SerialNumberChecker.test(
|
||||
new AtomicSerialNumbers());
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
No duplicates detected
|
||||
*/
|
@ -2,43 +2,19 @@
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
// {javap -c Atomicity}
|
||||
import java.util.concurrent.*;
|
||||
import onjava.TimedAbort;
|
||||
|
||||
public class Atomicity {
|
||||
int i;
|
||||
void f1() { i++; }
|
||||
void f2() { i += 3; }
|
||||
public static void test(IntTestable it) {
|
||||
new TimedAbort(4, "No failures found");
|
||||
CompletableFuture.runAsync(it);
|
||||
while(true) {
|
||||
int val = it.getAsInt();
|
||||
if(val % 2 != 0) {
|
||||
System.out.println("failed with: " + val);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
Compiled from "Atomicity.java"
|
||||
public class Atomicity {
|
||||
int i;
|
||||
|
||||
public Atomicity();
|
||||
Code:
|
||||
0: aload_0
|
||||
1: invokespecial #1 // Method
|
||||
java/lang/Object."<init>":()V
|
||||
4: return
|
||||
|
||||
void f1();
|
||||
Code:
|
||||
0: aload_0
|
||||
1: dup
|
||||
2: getfield #2 // Field i:I
|
||||
5: iconst_1
|
||||
6: iadd
|
||||
7: putfield #2 // Field i:I
|
||||
10: return
|
||||
|
||||
void f2();
|
||||
Code:
|
||||
0: aload_0
|
||||
1: dup
|
||||
2: getfield #2 // Field i:I
|
||||
5: iconst_3
|
||||
6: iadd
|
||||
7: putfield #2 // Field i:I
|
||||
10: return
|
||||
}
|
||||
*/
|
||||
|
@ -1,34 +0,0 @@
|
||||
// lowlevel/AtomicityTest.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
import java.util.concurrent.*;
|
||||
import onjava.TimedAbort;
|
||||
|
||||
public class AtomicityTest implements Runnable {
|
||||
private int i = 0;
|
||||
public int getValue() { return i; }
|
||||
private synchronized void evenIncrement() {
|
||||
i++; i++;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
while(true)
|
||||
evenIncrement();
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
new TimedAbort(4, "No failures found");
|
||||
AtomicityTest at = new AtomicityTest();
|
||||
CompletableFuture.runAsync(at);
|
||||
while(true) {
|
||||
int val = at.getValue();
|
||||
if(val % 2 != 0) {
|
||||
System.out.println("failed with: " + val);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
failed with: 21
|
||||
*/
|
29
lowlevel/CircularSet.java
Normal file
29
lowlevel/CircularSet.java
Normal file
@ -0,0 +1,29 @@
|
||||
// lowlevel/CircularSet.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
// Reuses storage so we don't run out of memory
|
||||
import java.util.*;
|
||||
|
||||
public class CircularSet {
|
||||
private int[] array;
|
||||
private int size;
|
||||
private int index = 0;
|
||||
public CircularSet(int size) {
|
||||
this.size = size;
|
||||
array = new int[size];
|
||||
// Initialize to a value not produced
|
||||
// by SerialNumbers:
|
||||
Arrays.fill(array, -1);
|
||||
}
|
||||
public synchronized void add(int i) {
|
||||
array[index] = i;
|
||||
// Wrap index and write over old elements:
|
||||
index = ++index % size;
|
||||
}
|
||||
public synchronized boolean contains(int val) {
|
||||
for(int i = 0; i < size; i++)
|
||||
if(array[i] == val) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
15
lowlevel/IntTestable.java
Normal file
15
lowlevel/IntTestable.java
Normal file
@ -0,0 +1,15 @@
|
||||
// lowlevel/IntTestable.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
import java.util.function.*;
|
||||
|
||||
public abstract class
|
||||
IntTestable implements Runnable, IntSupplier {
|
||||
abstract void evenIncrement();
|
||||
@Override
|
||||
public void run() {
|
||||
while(true)
|
||||
evenIncrement();
|
||||
}
|
||||
}
|
44
lowlevel/NotAtomic.java
Normal file
44
lowlevel/NotAtomic.java
Normal file
@ -0,0 +1,44 @@
|
||||
// lowlevel/NotAtomic.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
// {javap -c NotAtomic}
|
||||
|
||||
public class NotAtomic {
|
||||
int i;
|
||||
void f1() { i++; }
|
||||
void f2() { i += 3; }
|
||||
}
|
||||
/* Output:
|
||||
Compiled from "NotAtomic.java"
|
||||
public class NotAtomic {
|
||||
int i;
|
||||
|
||||
public NotAtomic();
|
||||
Code:
|
||||
0: aload_0
|
||||
1: invokespecial #1 // Method
|
||||
java/lang/Object."<init>":()V
|
||||
4: return
|
||||
|
||||
void f1();
|
||||
Code:
|
||||
0: aload_0
|
||||
1: dup
|
||||
2: getfield #2 // Field i:I
|
||||
5: iconst_1
|
||||
6: iadd
|
||||
7: putfield #2 // Field i:I
|
||||
10: return
|
||||
|
||||
void f2();
|
||||
Code:
|
||||
0: aload_0
|
||||
1: dup
|
||||
2: getfield #2 // Field i:I
|
||||
5: iconst_3
|
||||
6: iadd
|
||||
7: putfield #2 // Field i:I
|
||||
10: return
|
||||
}
|
||||
*/
|
21
lowlevel/SafeReturn.java
Normal file
21
lowlevel/SafeReturn.java
Normal file
@ -0,0 +1,21 @@
|
||||
// lowlevel/SafeReturn.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
import java.util.function.*;
|
||||
import java.util.concurrent.*;
|
||||
import onjava.TimedAbort;
|
||||
|
||||
public class SafeReturn extends IntTestable {
|
||||
private int i = 0;
|
||||
public synchronized int getAsInt() { return i; }
|
||||
public synchronized void evenIncrement() {
|
||||
i++; i++;
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
Atomicity.test(new SafeReturn());
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
No failures found
|
||||
*/
|
@ -2,43 +2,20 @@
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
// Operations that might seem safe are not,
|
||||
// when threads are present.
|
||||
import java.util.*;
|
||||
// Test SerialNumbers implementations for thread-safety
|
||||
import java.util.concurrent.*;
|
||||
import onjava.Nap;
|
||||
|
||||
// Reuses storage so we don't run out of memory:
|
||||
class CircularSet {
|
||||
private int[] array;
|
||||
private int size;
|
||||
private int index = 0;
|
||||
public CircularSet(int size) {
|
||||
array = new int[size];
|
||||
// Initialize to a value not produced
|
||||
// by the SerialNumberSupplier:
|
||||
Arrays.fill(array, -1);
|
||||
this.size = size;
|
||||
}
|
||||
public synchronized void add(int i) {
|
||||
array[index] = i;
|
||||
// Wrap index and write over old elements:
|
||||
index = ++index % size;
|
||||
}
|
||||
public synchronized boolean contains(int val) {
|
||||
for(int i = 0; i < size; i++)
|
||||
if(array[i] == val) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class SerialNumberChecker implements Runnable {
|
||||
private CircularSet serials = new CircularSet(1000);
|
||||
private SerialNumbers producer;
|
||||
public SerialNumberChecker(SerialNumbers producer) {
|
||||
this.producer = producer;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
while(true) {
|
||||
int serial =
|
||||
SerialNumberSupplier.nextSerialNumber();
|
||||
int serial = producer.nextSerialNumber();
|
||||
if(serials.contains(serial)) {
|
||||
System.out.println("Duplicate: " + serial);
|
||||
System.exit(0);
|
||||
@ -46,13 +23,10 @@ public class SerialNumberChecker implements Runnable {
|
||||
serials.add(serial);
|
||||
}
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
static void test(SerialNumbers producer) {
|
||||
for(int i = 0; i < 10; i++)
|
||||
CompletableFuture.runAsync(
|
||||
new SerialNumberChecker());
|
||||
new SerialNumberChecker(producer));
|
||||
new Nap(4000, "No duplicates detected");
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
Duplicate: 4119
|
||||
*/
|
||||
|
13
lowlevel/SerialNumberTest.java
Normal file
13
lowlevel/SerialNumberTest.java
Normal file
@ -0,0 +1,13 @@
|
||||
// lowlevel/SerialNumberTest.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
|
||||
public class SerialNumberTest {
|
||||
public static void main(String[] args) {
|
||||
SerialNumberChecker.test(new SerialNumbers());
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
Duplicate: 4119
|
||||
*/
|
@ -1,11 +1,11 @@
|
||||
// lowlevel/SerialNumberSupplier.java
|
||||
// lowlevel/SerialNumbers.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
|
||||
public class SerialNumberSupplier {
|
||||
private static volatile int serialNumber = 0;
|
||||
public static int nextSerialNumber() {
|
||||
public class SerialNumbers {
|
||||
private volatile int serialNumber = 0;
|
||||
public int nextSerialNumber() {
|
||||
return serialNumber++; // Not thread-safe
|
||||
}
|
||||
}
|
19
lowlevel/SynchronizedSerialNumbers.java
Normal file
19
lowlevel/SynchronizedSerialNumbers.java
Normal file
@ -0,0 +1,19 @@
|
||||
// lowlevel/SynchronizedSerialNumbers.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
|
||||
public class
|
||||
SynchronizedSerialNumbers extends SerialNumbers {
|
||||
private int serialNumber = 0;
|
||||
public synchronized int nextSerialNumber() {
|
||||
return serialNumber++;
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SerialNumberChecker.test(
|
||||
new SynchronizedSerialNumbers());
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
No duplicates detected
|
||||
*/
|
21
lowlevel/UnsafeReturn.java
Normal file
21
lowlevel/UnsafeReturn.java
Normal file
@ -0,0 +1,21 @@
|
||||
// lowlevel/UnsafeReturn.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
import java.util.function.*;
|
||||
import java.util.concurrent.*;
|
||||
import onjava.TimedAbort;
|
||||
|
||||
public class UnsafeReturn extends IntTestable {
|
||||
private int i = 0;
|
||||
public int getAsInt() { return i; }
|
||||
public synchronized void evenIncrement() {
|
||||
i++; i++;
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
Atomicity.test(new UnsafeReturn());
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
failed with: 21
|
||||
*/
|
Loading…
x
Reference in New Issue
Block a user