package com.tddinaction.concurrency.threadsafety;
import java.util.concurrent.CyclicBarrier;
import org.junit.Assert;
import org.junit.Test;
public class TestThreadSafety {
@Test
public void testBasicFunctionality() throws Exception {
Counter counter = new Counter();
Assert.assertEquals(0, counter.value());
counter.increment();
Assert.assertEquals(1, counter.value());
counter.increment();
Assert.assertEquals(2, counter.value());
}
@Test
public void testForThreadSafety() throws Exception {
final Counter codeUnderTest = new Counter();
final int numberOfThreads = 20;
final int incrementsPerThread = 100;
Runnable runnable = new Runnable() {
public void run() {
for (int i = 0; i < incrementsPerThread; i++) {
codeUnderTest.increment();
}
}
};
for (int i = 0; i < numberOfThreads; i++) {
new Thread(runnable).start();
}
Thread.sleep(500);
Assert.assertEquals(numberOfThreads * incrementsPerThread,
codeUnderTest.value());
}
@Test
public void testForThreadSafetyUsingBarrierToMaximizeConcurrency()
throws Exception {
final Counter codeUnderTest = new Counter();
final int numberOfThreads = 20;
final int incrementsPerThread = 10000;
CyclicBarrier entryBarrier = new CyclicBarrier(
numberOfThreads + 1);
CyclicBarrier exitBarrier = new CyclicBarrier(
numberOfThreads + 1);
Runnable runnable = new Runnable() {
public void run() {
for (int i = 0; i < incrementsPerThread; i++) {
codeUnderTest.increment();
}
}
};
for (int i = 0; i < numberOfThreads; i++) {
new SynchedThread(runnable, entryBarrier, exitBarrier)
.start();
}
Assert.assertEquals(0, codeUnderTest.value());
entryBarrier.await(); // let threads proceed when all have been
// started
exitBarrier.await(); // wait for all threads to finish their
// execution
Assert.assertEquals(numberOfThreads * incrementsPerThread,
codeUnderTest.value());
}
}