Skip to content

Instantly share code, notes, and snippets.

@lotabout
Created August 21, 2018 01:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lotabout/d69d4664a1d3c6b25e475e8df6faa1d4 to your computer and use it in GitHub Desktop.
Save lotabout/d69d4664a1d3c6b25e475e8df6faa1d4 to your computer and use it in GitHub Desktop.
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
Copy link
Author

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