Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SyncTest {
private enum TestType {
SYNCHRONIZED, VOLATILE, ATOMIC, LOCK, FAIR_LOCK
}
private final Lock lock = new ReentrantLock(false);
private final Lock fairLock = new ReentrantLock(true);
private int synchronizedCounter;
private int fairLockCounter;
private int lockCounter;
private volatile int volatileCounter;
private final AtomicInteger atomicCounter = new AtomicInteger();
public static void main(String[] args) throws Exception {
new SyncTest().run();
}
public void run() throws Exception {
System.out.println("Initializing test...");
System.out.println();
System.out.printf("%s (%s) version %s\n", System.getProperty("os.name"), System.getProperty("os.arch"),
System.getProperty("os.version"));
System.out.println();
System.out.printf("java.version %s\n", System.getProperty("java.version"));
System.out.printf("%s (%s)\n", System.getProperty("java.runtime.name"),
System.getProperty("java.runtime.version"));
System.out.printf("%s (build %s, %s)\n", System.getProperty("java.vm.name"),
System.getProperty("java.vm.version"), System.getProperty("java.vm.info"));
System.out.println();
int jvmStabilizationEndValue = 100000;
int endValue = 10000000;
System.out.println("JVM Stabilization Count Limit: " + endValue);
System.out.println("Test Count Limit: " + endValue);
System.out.println();
// run to let JVM do any optimizations and stabilize
runIndividualTest(TestType.SYNCHRONIZED, 1, jvmStabilizationEndValue);
runIndividualTest(TestType.VOLATILE, 1, jvmStabilizationEndValue);
runIndividualTest(TestType.ATOMIC, 1, jvmStabilizationEndValue);
runIndividualTest(TestType.LOCK, 1, jvmStabilizationEndValue);
runTestsConcurrently(1, jvmStabilizationEndValue);
runTestsSerially(1, jvmStabilizationEndValue);
System.out
.printf("Threads Syncronized Volatile Atomic Lock FairLock Serial Concurrent\n");
runAllTests(1, endValue);
runAllTests(2, endValue);
runAllTests(3, endValue);
runAllTests(4, endValue);
runAllTests(5, endValue);
runAllTests(6, endValue);
runAllTests(7, endValue);
runAllTests(8, endValue);
runAllTests(9, endValue);
runAllTests(12, endValue);
runAllTests(24, endValue);
runAllTests(48, endValue);
runAllTests(96, endValue);
System.out.println("\n Test complete");
}
private void runAllTests(int threadCount, int endValue) throws Exception {
long synchronizedElapsed = runIndividualTest(TestType.SYNCHRONIZED, threadCount, endValue);
long volatileElapsed = runIndividualTest(TestType.VOLATILE, threadCount, endValue);
long atomicElapsed = runIndividualTest(TestType.ATOMIC, threadCount, endValue);
long lockElapsed = runIndividualTest(TestType.LOCK, threadCount, endValue);
long serialElapsed = runTestsSerially(threadCount, endValue);
long concurrenteElapsed = runTestsConcurrently(threadCount, endValue);
if (concurrenteElapsed > 0) {
System.out.printf("%7d %11d %11d %11d %11d %11s %11d %11d\n", threadCount, synchronizedElapsed,
volatileElapsed, atomicElapsed, lockElapsed, "", serialElapsed, concurrenteElapsed);
} else if (threadCount <= 2) {
long fairLockElapsed = runIndividualTest(TestType.FAIR_LOCK, threadCount, endValue);
System.out.printf("%7d %11d %11d %11d %11d %11d %11d\n", threadCount, synchronizedElapsed, volatileElapsed,
atomicElapsed, lockElapsed, fairLockElapsed, serialElapsed);
} else {
System.out.printf("%7d %11d %11d %11d %11d %11s %11d\n", threadCount, synchronizedElapsed, volatileElapsed,
atomicElapsed, lockElapsed, "", serialElapsed);
}
}
private long runIndividualTest(final TestType testType, int threadCount, final int endValue) throws Exception {
final CyclicBarrier testsStarted = new CyclicBarrier(threadCount + 1);
final CountDownLatch testsComplete = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
startTestThread(testType, testsStarted, testsComplete, endValue);
}
return waitForTests(testsStarted, testsComplete);
}
private long runTestsSerially(int threadCount, final int endValue) throws Exception {
final CyclicBarrier testsStarted = new CyclicBarrier(threadCount + 1);
final CountDownLatch testsComplete = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
Thread t = new Thread() {
public void run() {
try {
testsStarted.await();
runSynchronizedTest(endValue);
runVolatileTest(endValue);
runAtomicTest(endValue);
runLockTest(endValue);
} catch (Throwable t) {
t.printStackTrace();
} finally {
testsComplete.countDown();
}
}
};
t.start();
}
return waitForTests(testsStarted, testsComplete);
}
private long runTestsConcurrently(int threadCount, int endValue) throws Exception {
if (threadCount % 4 != 0) {
return -1;
}
final CyclicBarrier testsStarted = new CyclicBarrier(threadCount + 1);
final CountDownLatch testsComplete = new CountDownLatch(threadCount);
threadCount /= 4;
for (int i = 0; i < threadCount; i++) {
startTestThread(TestType.SYNCHRONIZED, testsStarted, testsComplete, endValue);
startTestThread(TestType.VOLATILE, testsStarted, testsComplete, endValue);
startTestThread(TestType.ATOMIC, testsStarted, testsComplete, endValue);
startTestThread(TestType.LOCK, testsStarted, testsComplete, endValue);
}
return waitForTests(testsStarted, testsComplete);
}
private void startTestThread(final TestType testType, final CyclicBarrier testsStarted,
final CountDownLatch testsComplete, final int endValue) {
Thread t = new Thread() {
public void run() {
try {
testsStarted.await();
switch (testType) {
case SYNCHRONIZED:
runSynchronizedTest(endValue);
break;
case VOLATILE:
runVolatileTest(endValue);
break;
case ATOMIC:
runAtomicTest(endValue);
break;
case LOCK:
runLockTest(endValue);
break;
case FAIR_LOCK:
runFairLockTest(endValue);
break;
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
testsComplete.countDown();
}
}
};
t.start();
}
private long waitForTests(CyclicBarrier testsStarted, CountDownLatch testsComplete) throws Exception {
testsStarted.await();
long startTime = System.currentTimeMillis();
testsComplete.await();
long endTime = System.currentTimeMillis();
reset();
return endTime - startTime;
}
private void reset() {
synchronized (this) {
synchronizedCounter = 0;
}
volatileCounter = 0;
atomicCounter.set(0);
lock.lock();
try {
lockCounter = 0;
} finally {
lock.unlock();
}
fairLock.lock();
try {
fairLockCounter = 0;
} finally {
fairLock.unlock();
}
}
private void runSynchronizedTest(long endValue) {
boolean run = true;
while (run) {
run = incrementSynchronizedCounter(endValue);
}
}
private synchronized boolean incrementSynchronizedCounter(long endValue) {
return ++synchronizedCounter < endValue;
}
private void runVolatileTest(long endValue) {
boolean run = true;
while (run) {
run = ++volatileCounter < endValue;
}
}
private void runAtomicTest(long endValue) {
boolean run = true;
while (run) {
run = atomicCounter.incrementAndGet() < endValue;
}
}
private void runLockTest(long endValue) {
boolean run = true;
while (run) {
lock.lock();
try {
run = ++lockCounter < endValue;
} finally {
lock.unlock();
}
}
}
private void runFairLockTest(long endValue) {
boolean run = true;
while (run) {
fairLock.lock();
try {
run = ++fairLockCounter < endValue;
} finally {
fairLock.unlock();
}
}
}
}
@lotabout

This comment has been minimized.

Copy link
Owner Author

@lotabout lotabout commented Aug 21, 2018

Mac OS X (x86_64) version 10.12.6

java.version 1.8.0_121
Java(TM) SE Runtime Environment (1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

JVM Stabilization Count Limit: 10000000
Test Count Limit: 10000000

Threads Syncronized    Volatile      Atomic        Lock    FairLock      Serial  Concurrent
      1         248          61          61         200         214         624
      2         550         494         187        1196       32023        2403
      3         505         884         233         437                    2173
      4         540        1209         316         546                    2619        1206
      5         529        1069         255         559                    2671
      6         554        1136         319         572                    2498
      7         552        1090         316         573                    2536
      8         555        1091         322         569                    2430        1898
      9         554        1174         309         475                    2472
     12         570        1424         293         494                    2769        1160
     24         586        2427         271         506                    4029        1160
     48         590        4687         264         530                    6271        1569
     96         583        7922         106         504                   10612        2729

Test complete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment