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 5031862 8140471 37 * @summary Checks for responsiveness of locks to timeouts. 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.ThreadLocalRandom; 47 import java.util.concurrent.TimeUnit; 48 import java.util.concurrent.locks.ReentrantLock; 49 import jdk.test.lib.Utils; 50 51 public final class TimeoutLockLoops { 52 static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); 53 static final ExecutorService pool = Executors.newCachedThreadPool(); 54 static boolean print = false; 55 static final long TIMEOUT = 10; 56 57 public static void main(String[] args) throws Exception { 58 int maxThreads = 8; 59 if (args.length > 0) 60 maxThreads = Integer.parseInt(args[0]); 61 62 print = true; 63 64 for (int i = 1; i <= maxThreads; i += (i+1) >>> 1) { 65 System.out.print("Threads: " + i); 66 new ReentrantLockLoop(i).test(); 67 } 68 pool.shutdown(); 69 if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) 70 throw new Error(); 71 } 72 73 static final class ReentrantLockLoop implements Runnable { 74 private int v = ThreadLocalRandom.current().nextInt(); 75 private volatile int result = 17; 76 private final ReentrantLock lock = new ReentrantLock(); 77 private final LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer(); 78 private final CyclicBarrier barrier; 79 private final int nthreads; 80 private volatile Throwable fail = null; 81 ReentrantLockLoop(int nthreads) { 82 this.nthreads = nthreads; 83 barrier = new CyclicBarrier(nthreads+1, timer); 84 } 85 86 final void test() throws Exception { 87 for (int i = 0; i < nthreads; ++i) { 88 lock.lock(); 89 pool.execute(this); 90 lock.unlock(); 91 } 92 barrier.await(); 93 Thread.sleep(ThreadLocalRandom.current().nextInt(5)); 94 while (!lock.tryLock()); // Jam lock 95 // lock.lock(); 96 barrier.await(); 97 if (print) { 98 long time = timer.getTime(); 99 double secs = (double)(time) / 1000000000.0; 100 System.out.println("\t " + secs + "s run time"); 101 } 102 103 int r = result; 104 if (r == 0) // avoid overoptimization 105 System.out.println("useless result: " + r); 106 if (fail != null) throw new RuntimeException(fail); 107 } 108 109 public final void run() { 110 try { 111 barrier.await(); 112 int sum = v; 113 int x = 17; 114 final ReentrantLock lock = this.lock; 115 while (lock.tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) { 116 try { 117 v = x = LoopHelpers.compute1(v); 118 } 119 finally { 120 lock.unlock(); 121 } 122 sum += LoopHelpers.compute2(x); 123 } 124 barrier.await(); 125 result += sum; 126 } 127 catch (Throwable ex) { 128 fail = ex; 129 throw new RuntimeException(ex); 130 } 131 } 132 } 133 }