Created
August 21, 2018 01:52
-
-
Save lotabout/d69d4664a1d3c6b25e475e8df6faa1d4 to your computer and use it in GitHub Desktop.
Copied from https://objectpartners.com/2011/11/29/java-synchronization-method-performance-comparison/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} | |
} |
Author
lotabout
commented
Aug 21, 2018
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment