1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 */ 22 23 /* 24 * This file is available under and governed by the GNU General Public 25 * License version 2 only, as published by the Free Software Foundation. 26 * However, the following notice accompanied the original version of this 27 * file: 28 * 29 * Written by Doug Lea with assistance from members of JCP JSR-166 30 * Expert Group and released to the public domain, as explained at 31 * http://creativecommons.org/publicdomain/zero/1.0/ 32 */ 33 34 /* 35 * @test 36 * @bug 4486658 37 * @summary multiple threads using a single lock 38 * @library /test/lib 39 */ 40 41 import static java.util.concurrent.TimeUnit.MILLISECONDS; 42 43 import java.util.concurrent.CyclicBarrier; 44 import java.util.concurrent.ExecutorService; 45 import java.util.concurrent.Executors; 46 import java.util.concurrent.locks.ReentrantLock; 47 import java.util.concurrent.ThreadLocalRandom; 48 import jdk.test.lib.Utils; 49 50 public final class SimpleReentrantLockLoops { 51 static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); 52 static final ExecutorService pool = Executors.newCachedThreadPool(); 53 static boolean print = false; 54 static int iters = 100_000; 55 56 public static void main(String[] args) throws Exception { 57 int maxThreads = 5; 58 if (args.length > 0) 59 maxThreads = Integer.parseInt(args[0]); 60 61 print = true; 62 63 int reps = 2; 64 for (int i = 1; i <= maxThreads; i += (i+1) >>> 1) { 65 int n = reps; 66 if (reps > 1) --reps; 67 while (n-- > 0) { 68 System.out.print("Threads: " + i); 69 new ReentrantLockLoop(i).test(); 70 } 71 } 72 pool.shutdown(); 73 if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) 74 throw new Error(); 75 } 76 77 static final class ReentrantLockLoop implements Runnable { 78 private int v = ThreadLocalRandom.current().nextInt(); 79 private volatile int result = 17; 80 private final ReentrantLock lock = new ReentrantLock(); 81 private final LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer(); 82 private final CyclicBarrier barrier; 83 private final int nthreads; 84 ReentrantLockLoop(int nthreads) { 85 this.nthreads = nthreads; 86 barrier = new CyclicBarrier(nthreads+1, timer); 87 } 88 89 final void test() throws Exception { 90 for (int i = 0; i < nthreads; ++i) 91 pool.execute(this); 92 barrier.await(); 93 barrier.await(); 94 if (print) { 95 long time = timer.getTime(); 96 long tpi = time / ((long)iters * nthreads); 97 System.out.print("\t" + LoopHelpers.rightJustify(tpi) + " ns per lock"); 98 double secs = (double)(time) / 1000000000.0; 99 System.out.println("\t " + secs + "s run time"); 100 } 101 102 int r = result; 103 if (r == 0) // avoid overoptimization 104 System.out.println("useless result: " + r); 105 } 106 107 public final void run() { 108 try { 109 barrier.await(); 110 int sum = v; 111 int x = 0; 112 int n = iters; 113 do { 114 lock.lock(); 115 try { 116 if ((n & 255) == 0) 117 v = x = LoopHelpers.compute2(LoopHelpers.compute1(v)); 118 else 119 v = x += ~(v - n); 120 } 121 finally { 122 lock.unlock(); 123 } 124 // Once in a while, do something more expensive 125 if ((~n & 255) == 0) { 126 sum += LoopHelpers.compute1(LoopHelpers.compute2(x)); 127 } 128 else 129 sum += sum ^ x; 130 } while (n-- > 0); 131 barrier.await(); 132 result += sum; 133 } 134 catch (Exception ex) { 135 return; 136 } 137 } 138 } 139 140 }