1 /* 2 * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package org.openjdk.bench.java.util.concurrent; 26 27 import org.openjdk.jmh.annotations.Benchmark; 28 import org.openjdk.jmh.annotations.BenchmarkMode; 29 import org.openjdk.jmh.annotations.Mode; 30 import org.openjdk.jmh.annotations.OutputTimeUnit; 31 import org.openjdk.jmh.annotations.Scope; 32 import org.openjdk.jmh.annotations.Setup; 33 import org.openjdk.jmh.annotations.State; 34 import org.openjdk.jmh.infra.Blackhole; 35 36 import java.io.IOException; 37 import java.io.ObjectInputStream; 38 import java.util.concurrent.Semaphore; 39 import java.util.concurrent.TimeUnit; 40 import java.util.concurrent.locks.AbstractQueuedSynchronizer; 41 import java.util.concurrent.locks.Condition; 42 import java.util.concurrent.locks.Lock; 43 import java.util.concurrent.locks.ReentrantLock; 44 import java.util.concurrent.locks.ReentrantReadWriteLock; 45 46 @BenchmarkMode(Mode.AverageTime) 47 @OutputTimeUnit(TimeUnit.NANOSECONDS) 48 @State(Scope.Benchmark) 49 public class Locks { 50 51 private ReentrantLock reentrantLock; 52 private ReentrantLock fairReentrantLock; 53 private ReentrantReadWriteLock reentrantRWLock; 54 private ReentrantReadWriteLock fairReentrantRWLock; 55 private Semaphore semaphore; 56 private Semaphore fairSemaphore; 57 private Lock reentrantWriteLock; 58 private Mutex mutex; 59 60 @Setup 61 public void setup() { 62 reentrantLock = new ReentrantLock(false); 63 fairReentrantLock = new ReentrantLock(true); 64 reentrantRWLock = new ReentrantReadWriteLock(false); 65 fairReentrantRWLock = new ReentrantReadWriteLock(true); 66 semaphore = new Semaphore(1, false); 67 fairSemaphore = new Semaphore(1, true); 68 reentrantWriteLock = new ReentrantReadWriteLock(false).writeLock(); 69 mutex = new Mutex(); 70 } 71 72 @Benchmark 73 public void testSynchronizedBlock() { 74 synchronized (this) { 75 Blackhole.consumeCPU(10); 76 } 77 Blackhole.consumeCPU(5); 78 } 79 80 @Benchmark 81 public void testFairReentrantLock() { 82 fairReentrantLock.lock(); 83 try { 84 Blackhole.consumeCPU(10); 85 } finally { 86 fairReentrantLock.unlock(); 87 } 88 Blackhole.consumeCPU(5); 89 } 90 91 @Benchmark 92 public void testReentrantLock() { 93 reentrantLock.lock(); 94 try { 95 Blackhole.consumeCPU(10); 96 } finally { 97 reentrantLock.unlock(); 98 } 99 Blackhole.consumeCPU(5); 100 } 101 102 @Benchmark 103 public void testFairReentrantReadWriteLock() { 104 fairReentrantRWLock.readLock().lock(); 105 try { 106 Blackhole.consumeCPU(10); 107 } finally { 108 fairReentrantRWLock.readLock().unlock(); 109 } 110 fairReentrantRWLock.writeLock().lock(); 111 try { 112 Blackhole.consumeCPU(10); 113 } finally { 114 fairReentrantRWLock.writeLock().unlock(); 115 } 116 Blackhole.consumeCPU(5); 117 } 118 119 @Benchmark 120 public void testReentrantReadWriteLock() { 121 reentrantRWLock.readLock().lock(); 122 try { 123 Blackhole.consumeCPU(10); 124 } finally { 125 reentrantRWLock.readLock().unlock(); 126 } 127 reentrantRWLock.writeLock().lock(); 128 try { 129 Blackhole.consumeCPU(10); 130 } finally { 131 reentrantRWLock.writeLock().unlock(); 132 } 133 Blackhole.consumeCPU(5); 134 } 135 136 @Benchmark 137 public void testReentrantWriteLock() { 138 reentrantWriteLock.lock(); 139 try { 140 Blackhole.consumeCPU(10); 141 } finally { 142 reentrantWriteLock.unlock(); 143 } 144 Blackhole.consumeCPU(5); 145 } 146 147 @Benchmark 148 public void testFairSemaphore() throws InterruptedException { 149 fairSemaphore.acquire(); 150 try { 151 Blackhole.consumeCPU(10); 152 } finally { 153 fairSemaphore.release(); 154 } 155 Blackhole.consumeCPU(5); 156 } 157 158 @Benchmark 159 public void testSemaphore() throws InterruptedException { 160 semaphore.acquire(); 161 try { 162 Blackhole.consumeCPU(10); 163 } finally { 164 semaphore.release(); 165 } 166 Blackhole.consumeCPU(5); 167 } 168 169 @Benchmark 170 public void testAbstractQueueSynchronizer() { 171 mutex.lock(); 172 try { 173 Blackhole.consumeCPU(10); 174 } finally { 175 mutex.unlock(); 176 } 177 Blackhole.consumeCPU(5); 178 } 179 180 @SuppressWarnings("serial") 181 private final class Mutex extends AbstractQueuedSynchronizer implements Lock, java.io.Serializable { 182 183 @Override 184 public boolean isHeldExclusively() { 185 return getState() == 1; 186 } 187 188 @Override 189 public boolean tryAcquire(int acquires) { 190 return compareAndSetState(0, 1); 191 } 192 193 @Override 194 public boolean tryRelease(int releases) { 195 setState(0); 196 return true; 197 } 198 199 @Override 200 public Condition newCondition() { 201 return new ConditionObject(); 202 } 203 204 private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { 205 s.defaultReadObject(); 206 setState(0); // reset to unlocked state 207 } 208 209 @Override 210 public void lock() { 211 acquire(1); 212 } 213 214 @Override 215 public boolean tryLock() { 216 return tryAcquire(1); 217 } 218 219 @Override 220 public void lockInterruptibly() throws InterruptedException { 221 acquireInterruptibly(1); 222 } 223 224 @Override 225 public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { 226 return tryAcquireNanos(1, unit.toNanos(timeout)); 227 } 228 229 @Override 230 public void unlock() { 231 release(1); 232 } 233 } 234 }