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