Skip to content

Commit a05aa3e

Browse files
committed
New/improved synchronization examples
1 parent 551389c commit a05aa3e

14 files changed

+240
-128
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// concurrent/SynchronizedConstructor.java
2+
// (c)2017 MindView LLC: see Copyright.txt
3+
// We make no guarantees that this code is fit for any purpose.
4+
// Visit http://OnJava8.com for more book information.
5+
import java.util.concurrent.atomic.*;
6+
7+
class SyncConstructor implements HasID {
8+
private final int id;
9+
private static Object constructorLock = new Object();
10+
public SyncConstructor(SharedArg sa) {
11+
synchronized(constructorLock) {
12+
id = sa.get();
13+
}
14+
}
15+
@Override
16+
public int getID() { return id; }
17+
}
18+
19+
public class SynchronizedConstructor {
20+
public static void main(String[] args) {
21+
Unsafe unsafe = new Unsafe();
22+
IDChecker.test(() -> new SyncConstructor(unsafe));
23+
}
24+
}
25+
/* Output:
26+
0
27+
*/

lowlevel/AtomicIntegerTest.java

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,14 @@
77
import java.util.*;
88
import onjava.*;
99

10-
public class AtomicIntegerTest implements Runnable {
10+
public class AtomicIntegerTest extends IntTestable {
1111
private AtomicInteger i = new AtomicInteger(0);
12-
public int getValue() { return i.get(); }
13-
private void evenIncrement() { i.addAndGet(2); }
14-
@Override
15-
public void run() {
16-
while(true)
17-
evenIncrement();
18-
}
12+
public int getAsInt() { return i.get(); }
13+
public void evenIncrement() { i.addAndGet(2); }
1914
public static void main(String[] args) {
20-
new TimedAbort(4, "No failures discovered");
21-
AtomicIntegerTest ait = new AtomicIntegerTest();
22-
CompletableFuture.runAsync(ait);
23-
while(true) {
24-
int val = ait.getValue();
25-
if(val % 2 != 0) {
26-
System.out.println(val);
27-
System.exit(0);
28-
}
29-
}
15+
Atomicity.test(new AtomicIntegerTest());
3016
}
3117
}
3218
/* Output:
33-
No failures discovered
19+
No failures found
3420
*/

lowlevel/AtomicSerialNumbers.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// lowlevel/AtomicSerialNumbers.java
2+
// (c)2017 MindView LLC: see Copyright.txt
3+
// We make no guarantees that this code is fit for any purpose.
4+
// Visit http://OnJava8.com for more book information.
5+
import java.util.concurrent.atomic.*;
6+
7+
public class
8+
AtomicSerialNumbers extends SerialNumbers {
9+
private AtomicInteger serialNumber =
10+
new AtomicInteger();
11+
public synchronized int nextSerialNumber() {
12+
return serialNumber.getAndIncrement();
13+
}
14+
public static void main(String[] args) {
15+
SerialNumberChecker.test(
16+
new AtomicSerialNumbers());
17+
}
18+
}
19+
/* Output:
20+
No duplicates detected
21+
*/

lowlevel/Atomicity.java

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,19 @@
22
// (c)2017 MindView LLC: see Copyright.txt
33
// We make no guarantees that this code is fit for any purpose.
44
// Visit http://OnJava8.com for more book information.
5-
// {javap -c Atomicity}
5+
import java.util.concurrent.*;
6+
import onjava.TimedAbort;
67

78
public class Atomicity {
8-
int i;
9-
void f1() { i++; }
10-
void f2() { i += 3; }
9+
public static void test(IntTestable it) {
10+
new TimedAbort(4, "No failures found");
11+
CompletableFuture.runAsync(it);
12+
while(true) {
13+
int val = it.getAsInt();
14+
if(val % 2 != 0) {
15+
System.out.println("failed with: " + val);
16+
System.exit(0);
17+
}
18+
}
19+
}
1120
}
12-
/* Output:
13-
Compiled from "Atomicity.java"
14-
public class Atomicity {
15-
int i;
16-
17-
public Atomicity();
18-
Code:
19-
0: aload_0
20-
1: invokespecial #1 // Method
21-
java/lang/Object."<init>":()V
22-
4: return
23-
24-
void f1();
25-
Code:
26-
0: aload_0
27-
1: dup
28-
2: getfield #2 // Field i:I
29-
5: iconst_1
30-
6: iadd
31-
7: putfield #2 // Field i:I
32-
10: return
33-
34-
void f2();
35-
Code:
36-
0: aload_0
37-
1: dup
38-
2: getfield #2 // Field i:I
39-
5: iconst_3
40-
6: iadd
41-
7: putfield #2 // Field i:I
42-
10: return
43-
}
44-
*/

lowlevel/AtomicityTest.java

Lines changed: 0 additions & 34 deletions
This file was deleted.

lowlevel/CircularSet.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// lowlevel/CircularSet.java
2+
// (c)2017 MindView LLC: see Copyright.txt
3+
// We make no guarantees that this code is fit for any purpose.
4+
// Visit http://OnJava8.com for more book information.
5+
// Reuses storage so we don't run out of memory
6+
import java.util.*;
7+
8+
public class CircularSet {
9+
private int[] array;
10+
private int size;
11+
private int index = 0;
12+
public CircularSet(int size) {
13+
this.size = size;
14+
array = new int[size];
15+
// Initialize to a value not produced
16+
// by SerialNumbers:
17+
Arrays.fill(array, -1);
18+
}
19+
public synchronized void add(int i) {
20+
array[index] = i;
21+
// Wrap index and write over old elements:
22+
index = ++index % size;
23+
}
24+
public synchronized boolean contains(int val) {
25+
for(int i = 0; i < size; i++)
26+
if(array[i] == val) return true;
27+
return false;
28+
}
29+
}

lowlevel/IntTestable.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// lowlevel/IntTestable.java
2+
// (c)2017 MindView LLC: see Copyright.txt
3+
// We make no guarantees that this code is fit for any purpose.
4+
// Visit http://OnJava8.com for more book information.
5+
import java.util.function.*;
6+
7+
public abstract class
8+
IntTestable implements Runnable, IntSupplier {
9+
abstract void evenIncrement();
10+
@Override
11+
public void run() {
12+
while(true)
13+
evenIncrement();
14+
}
15+
}

lowlevel/NotAtomic.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// lowlevel/NotAtomic.java
2+
// (c)2017 MindView LLC: see Copyright.txt
3+
// We make no guarantees that this code is fit for any purpose.
4+
// Visit http://OnJava8.com for more book information.
5+
// {javap -c NotAtomic}
6+
7+
public class NotAtomic {
8+
int i;
9+
void f1() { i++; }
10+
void f2() { i += 3; }
11+
}
12+
/* Output:
13+
Compiled from "NotAtomic.java"
14+
public class NotAtomic {
15+
int i;
16+
17+
public NotAtomic();
18+
Code:
19+
0: aload_0
20+
1: invokespecial #1 // Method
21+
java/lang/Object."<init>":()V
22+
4: return
23+
24+
void f1();
25+
Code:
26+
0: aload_0
27+
1: dup
28+
2: getfield #2 // Field i:I
29+
5: iconst_1
30+
6: iadd
31+
7: putfield #2 // Field i:I
32+
10: return
33+
34+
void f2();
35+
Code:
36+
0: aload_0
37+
1: dup
38+
2: getfield #2 // Field i:I
39+
5: iconst_3
40+
6: iadd
41+
7: putfield #2 // Field i:I
42+
10: return
43+
}
44+
*/

lowlevel/SafeReturn.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// lowlevel/SafeReturn.java
2+
// (c)2017 MindView LLC: see Copyright.txt
3+
// We make no guarantees that this code is fit for any purpose.
4+
// Visit http://OnJava8.com for more book information.
5+
import java.util.function.*;
6+
import java.util.concurrent.*;
7+
import onjava.TimedAbort;
8+
9+
public class SafeReturn extends IntTestable {
10+
private int i = 0;
11+
public synchronized int getAsInt() { return i; }
12+
public synchronized void evenIncrement() {
13+
i++; i++;
14+
}
15+
public static void main(String[] args) {
16+
Atomicity.test(new SafeReturn());
17+
}
18+
}
19+
/* Output:
20+
No failures found
21+
*/

lowlevel/SerialNumberChecker.java

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,57 +2,31 @@
22
// (c)2017 MindView LLC: see Copyright.txt
33
// We make no guarantees that this code is fit for any purpose.
44
// Visit http://OnJava8.com for more book information.
5-
// Operations that might seem safe are not,
6-
// when threads are present.
7-
import java.util.*;
5+
// Test SerialNumbers implementations for thread-safety
86
import java.util.concurrent.*;
97
import onjava.Nap;
108

11-
// Reuses storage so we don't run out of memory:
12-
class CircularSet {
13-
private int[] array;
14-
private int size;
15-
private int index = 0;
16-
public CircularSet(int size) {
17-
array = new int[size];
18-
// Initialize to a value not produced
19-
// by the SerialNumberSupplier:
20-
Arrays.fill(array, -1);
21-
this.size = size;
22-
}
23-
public synchronized void add(int i) {
24-
array[index] = i;
25-
// Wrap index and write over old elements:
26-
index = ++index % size;
27-
}
28-
public synchronized boolean contains(int val) {
29-
for(int i = 0; i < size; i++)
30-
if(array[i] == val) return true;
31-
return false;
32-
}
33-
}
34-
359
public class SerialNumberChecker implements Runnable {
3610
private CircularSet serials = new CircularSet(1000);
11+
private SerialNumbers producer;
12+
public SerialNumberChecker(SerialNumbers producer) {
13+
this.producer = producer;
14+
}
3715
@Override
3816
public void run() {
3917
while(true) {
40-
int serial =
41-
SerialNumberSupplier.nextSerialNumber();
18+
int serial = producer.nextSerialNumber();
4219
if(serials.contains(serial)) {
4320
System.out.println("Duplicate: " + serial);
4421
System.exit(0);
4522
}
4623
serials.add(serial);
4724
}
4825
}
49-
public static void main(String[] args) {
26+
static void test(SerialNumbers producer) {
5027
for(int i = 0; i < 10; i++)
5128
CompletableFuture.runAsync(
52-
new SerialNumberChecker());
29+
new SerialNumberChecker(producer));
5330
new Nap(4000, "No duplicates detected");
5431
}
5532
}
56-
/* Output:
57-
Duplicate: 4119
58-
*/

0 commit comments

Comments
 (0)