Moved code from book
Code from download was broken -- fixed that but discovered that code from book is different, so included that as well as the main file.
This commit is contained in:
parent
03f8233eab
commit
40d07cccc4
4
.gitignore
vendored
4
.gitignore
vendored
@ -50,4 +50,8 @@ annotations/Test1.txt
|
||||
annotations/Test2.txt
|
||||
io/*.out
|
||||
io/*.txt
|
||||
io/*.dat
|
||||
io/*.tmp
|
||||
io/test.zip
|
||||
io/test.gz
|
||||
io/X.file
|
||||
|
@ -11,6 +11,9 @@
|
||||
Ant available from: http://ant.apache.org/
|
||||
|
||||
To see options, type: ant -p
|
||||
|
||||
NOTE: Temporarily excluded
|
||||
annotations/build.xml
|
||||
</description>
|
||||
|
||||
<condition property="version1.8">
|
||||
@ -38,7 +41,6 @@
|
||||
io/build.xml
|
||||
xml/build.xml
|
||||
enumerated/build.xml
|
||||
annotations/build.xml
|
||||
concurrency/build.xml
|
||||
gui/build.xml
|
||||
swt/build.xml
|
||||
|
258
concurrency/SynchronizationComparisons-original-fixed.java
Normal file
258
concurrency/SynchronizationComparisons-original-fixed.java
Normal file
@ -0,0 +1,258 @@
|
||||
//: concurrency/SynchronizationComparisons.java
|
||||
// Comparing the performance of explicit Locks
|
||||
// and Atomics versus the synchronized keyword.
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.concurrent.locks.*;
|
||||
import java.util.*;
|
||||
import static net.mindview.util.Print.*;
|
||||
|
||||
abstract class Accumulator {
|
||||
public static long cycles = 50000L;
|
||||
// Number of Modifiers and Readers during each test:
|
||||
private static final int N = 4;
|
||||
public static ExecutorService exec =
|
||||
Executors.newFixedThreadPool(N*2);
|
||||
private static CyclicBarrier barrier =
|
||||
new CyclicBarrier(N*2 + 1);
|
||||
protected volatile int index = 0;
|
||||
protected volatile long value = 0;
|
||||
protected long duration = 0;
|
||||
protected String id = "error";
|
||||
protected final static int SIZE = 100000;
|
||||
protected static int[] preLoaded = new int[SIZE];
|
||||
static {
|
||||
// Load the array of random numbers:
|
||||
Random rand = new Random(47);
|
||||
for(int i = 0; i < SIZE; i++)
|
||||
preLoaded[i] = rand.nextInt();
|
||||
}
|
||||
public abstract void accumulate();
|
||||
public abstract long read();
|
||||
private class Modifier implements Runnable {
|
||||
public void run() {
|
||||
for(long i = 0; i < cycles; i++)
|
||||
accumulate();
|
||||
try {
|
||||
barrier.await();
|
||||
} catch(Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
private class Reader implements Runnable {
|
||||
private volatile long value;
|
||||
public void run() {
|
||||
for(long i = 0; i < cycles; i++)
|
||||
value = read();
|
||||
try {
|
||||
barrier.await();
|
||||
} catch(Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void timedTest() {
|
||||
long start = System.nanoTime();
|
||||
for(int i = 0; i < N; i++) {
|
||||
exec.execute(new Modifier());
|
||||
exec.execute(new Reader());
|
||||
}
|
||||
try {
|
||||
barrier.await();
|
||||
} catch(Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
duration = System.nanoTime() - start;
|
||||
printf("%-13s: %13d\n", id, duration);
|
||||
}
|
||||
public static void
|
||||
report(Accumulator acc1, Accumulator acc2) {
|
||||
printf("%-22s: %.2f\n", acc1.id + "/" + acc2.id,
|
||||
(double)acc1.duration/(double)acc2.duration);
|
||||
}
|
||||
}
|
||||
|
||||
class BaseLine extends Accumulator {
|
||||
{ id = "BaseLine"; }
|
||||
public void accumulate() {
|
||||
if(index >= SIZE - 1) index = 0;
|
||||
value += preLoaded[index++];
|
||||
}
|
||||
public long read() { return value; }
|
||||
}
|
||||
|
||||
class SynchronizedTest extends Accumulator {
|
||||
{ id = "synchronized"; }
|
||||
public synchronized void accumulate() {
|
||||
if(index >= SIZE - 1) index = 0;
|
||||
value += preLoaded[index++];
|
||||
}
|
||||
public synchronized long read() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
class LockTest extends Accumulator {
|
||||
{ id = "Lock"; }
|
||||
private Lock lock = new ReentrantLock();
|
||||
public void accumulate() {
|
||||
lock.lock();
|
||||
try {
|
||||
if(index >= SIZE - 1) index = 0;
|
||||
value += preLoaded[index++];
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
public long read() {
|
||||
lock.lock();
|
||||
try {
|
||||
return value;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AtomicTest extends Accumulator {
|
||||
{ id = "Atomic"; }
|
||||
private AtomicInteger index = new AtomicInteger(0);
|
||||
private AtomicLong value = new AtomicLong(0);
|
||||
public void accumulate() {
|
||||
// Oops! Relying on more than one Atomic at
|
||||
// a time doesn't work. But it still gives us
|
||||
// a performance indicator:
|
||||
int i = index.getAndIncrement();
|
||||
if(++i >= SIZE - 1) {
|
||||
i = 0;
|
||||
index.set(i);
|
||||
}
|
||||
value.getAndAdd(preLoaded[i]);
|
||||
}
|
||||
public long read() { return value.get(); }
|
||||
}
|
||||
|
||||
public class SynchronizationComparisons {
|
||||
static BaseLine baseLine = new BaseLine();
|
||||
static SynchronizedTest synch = new SynchronizedTest();
|
||||
static LockTest lock = new LockTest();
|
||||
static AtomicTest atomic = new AtomicTest();
|
||||
static void test() {
|
||||
print("============================");
|
||||
printf("%-12s : %13d\n", "Cycles", Accumulator.cycles);
|
||||
baseLine.timedTest();
|
||||
synch.timedTest();
|
||||
lock.timedTest();
|
||||
atomic.timedTest();
|
||||
Accumulator.report(synch, baseLine);
|
||||
Accumulator.report(lock, baseLine);
|
||||
Accumulator.report(atomic, baseLine);
|
||||
Accumulator.report(synch, lock);
|
||||
Accumulator.report(synch, atomic);
|
||||
Accumulator.report(lock, atomic);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
int iterations = 5; // Default
|
||||
if(args.length > 0) // Optionally change iterations
|
||||
iterations = new Integer(args[0]);
|
||||
// The first time fills the thread pool:
|
||||
print("Warmup");
|
||||
baseLine.timedTest();
|
||||
// Now the initial test doesn't include the cost
|
||||
// of starting the threads for the first time.
|
||||
// Produce multiple data points:
|
||||
for(int i = 0; i < iterations; i++) {
|
||||
test();
|
||||
Accumulator.cycles *= 2;
|
||||
}
|
||||
Accumulator.exec.shutdown();
|
||||
}
|
||||
} /* Output: (Sample)
|
||||
Warmup
|
||||
BaseLine : 34237033
|
||||
============================
|
||||
Cycles : 50000
|
||||
BaseLine : 20966632
|
||||
synchronized : 24326555
|
||||
Lock : 53669950
|
||||
Atomic : 30552487
|
||||
synchronized/BaseLine : 1.16
|
||||
Lock/BaseLine : 2.56
|
||||
Atomic/BaseLine : 1.46
|
||||
synchronized/Lock : 0.45
|
||||
synchronized/Atomic : 0.79
|
||||
Lock/Atomic : 1.76
|
||||
============================
|
||||
Cycles : 100000
|
||||
BaseLine : 41512818
|
||||
synchronized : 43843003
|
||||
Lock : 87430386
|
||||
Atomic : 51892350
|
||||
synchronized/BaseLine : 1.06
|
||||
Lock/BaseLine : 2.11
|
||||
Atomic/BaseLine : 1.25
|
||||
synchronized/Lock : 0.50
|
||||
synchronized/Atomic : 0.84
|
||||
Lock/Atomic : 1.68
|
||||
============================
|
||||
Cycles : 200000
|
||||
BaseLine : 80176670
|
||||
synchronized : 5455046661
|
||||
Lock : 177686829
|
||||
Atomic : 101789194
|
||||
synchronized/BaseLine : 68.04
|
||||
Lock/BaseLine : 2.22
|
||||
Atomic/BaseLine : 1.27
|
||||
synchronized/Lock : 30.70
|
||||
synchronized/Atomic : 53.59
|
||||
Lock/Atomic : 1.75
|
||||
============================
|
||||
Cycles : 400000
|
||||
BaseLine : 160383513
|
||||
synchronized : 780052493
|
||||
Lock : 362187652
|
||||
Atomic : 202030984
|
||||
synchronized/BaseLine : 4.86
|
||||
Lock/BaseLine : 2.26
|
||||
Atomic/BaseLine : 1.26
|
||||
synchronized/Lock : 2.15
|
||||
synchronized/Atomic : 3.86
|
||||
Lock/Atomic : 1.79
|
||||
============================
|
||||
Cycles : 800000
|
||||
BaseLine : 322064955
|
||||
synchronized : 336155014
|
||||
Lock : 704615531
|
||||
Atomic : 393231542
|
||||
synchronized/BaseLine : 1.04
|
||||
Lock/BaseLine : 2.19
|
||||
Atomic/BaseLine : 1.22
|
||||
synchronized/Lock : 0.47
|
||||
synchronized/Atomic : 0.85
|
||||
Lock/Atomic : 1.79
|
||||
============================
|
||||
Cycles : 1600000
|
||||
BaseLine : 650004120
|
||||
synchronized : 52235762925
|
||||
Lock : 1419602771
|
||||
Atomic : 796950171
|
||||
synchronized/BaseLine : 80.36
|
||||
Lock/BaseLine : 2.18
|
||||
Atomic/BaseLine : 1.23
|
||||
synchronized/Lock : 36.80
|
||||
synchronized/Atomic : 65.54
|
||||
Lock/Atomic : 1.78
|
||||
============================
|
||||
Cycles : 3200000
|
||||
BaseLine : 1285664519
|
||||
synchronized : 96336767661
|
||||
Lock : 2846988654
|
||||
Atomic : 1590545726
|
||||
synchronized/BaseLine : 74.93
|
||||
Lock/BaseLine : 2.21
|
||||
Atomic/BaseLine : 1.24
|
||||
synchronized/Lock : 33.84
|
||||
synchronized/Atomic : 60.57
|
||||
Lock/Atomic : 1.79
|
||||
*///:~
|
@ -136,7 +136,6 @@
|
||||
failonerror="true"
|
||||
fork="true">
|
||||
<arg line='"D.*\.java"'/>
|
||||
|
||||
</java>
|
||||
</target>
|
||||
|
||||
@ -148,7 +147,6 @@
|
||||
failonerror="true"
|
||||
fork="true">
|
||||
<arg line='"D.*\.java"'/>
|
||||
|
||||
</java>
|
||||
</target>
|
||||
|
||||
@ -160,7 +158,6 @@
|
||||
failonerror="true"
|
||||
fork="true">
|
||||
<arg line='"D.*\.java"'/>
|
||||
|
||||
</java>
|
||||
</target>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user