BusyLock.java revision 7711:e684445431fa
1/*
2 * Copyright (c) 2014, 2015, 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 */
24
25package rtm;
26
27import java.util.concurrent.BrokenBarrierException;
28import java.util.concurrent.CyclicBarrier;
29
30/**
31 * Test case for busy lock scenario.
32 * One thread enters the monitor and sleep for a while.
33 * Another thread is blocked on the same monitor.
34 */
35public class BusyLock implements CompilableTest, Runnable {
36    private static final int DEFAULT_TIMEOUT = 1000;
37    private final CyclicBarrier barrier;
38
39    // Following field have to be static in order to avoid escape analysis.
40    @SuppressWarnings("UnsuedDeclaration")
41    private static int field = 0;
42    protected final Object monitor;
43    protected final int timeout;
44
45    public BusyLock() {
46        this(BusyLock.DEFAULT_TIMEOUT);
47    }
48
49    public BusyLock(int timeout) {
50        this.timeout = timeout;
51        this.monitor = new Object();
52        this.barrier = new CyclicBarrier(2);
53    }
54
55    @Override
56    public void run() {
57        try {
58            synchronized (monitor) {
59                barrier.await();
60                Thread.sleep(timeout);
61            }
62        } catch (InterruptedException | BrokenBarrierException e) {
63            throw new RuntimeException("Synchronization error happened.", e);
64        }
65    }
66
67    public void syncAndTest() {
68        try {
69            // wait until monitor is locked by a ::run method
70            barrier.await();
71        } catch (InterruptedException | BrokenBarrierException e) {
72            throw new RuntimeException("Synchronization error happened.", e);
73        }
74        test();
75    }
76
77    public void test() {
78        synchronized(monitor) {
79            BusyLock.field++;
80        }
81    }
82
83    @Override
84    public String getMethodWithLockName() {
85        return this.getClass().getName() + "::test";
86    }
87
88    @Override
89    public String[] getMethodsToCompileNames() {
90        return new String[] { getMethodWithLockName() };
91    }
92
93    /**
94     * Usage:
95     * BusyLock [ <inflate monitor> [ <timeout> ] ]
96     *
97     * Default values are:
98     * <ul>
99     *     <li>inflate monitor = {@code true}</li>
100     *     <li>timeout = {@code BusyLock.DEFAULT_TIMEOUT}</li>
101     * </ul>
102     */
103    public static void main(String args[]) throws Exception {
104        int timeoutValue = BusyLock.DEFAULT_TIMEOUT;
105        boolean inflateMonitor = true;
106
107        if (args.length > 0 ) {
108            inflateMonitor = Boolean.valueOf(args[0]);
109
110            if (args.length > 1) {
111                timeoutValue = Integer.valueOf(args[1]);
112            }
113        }
114
115        BusyLock busyLock = new BusyLock(timeoutValue);
116
117        if (inflateMonitor) {
118            AbortProvoker.inflateMonitor(busyLock.monitor);
119        }
120
121        Thread t = new Thread(busyLock);
122        t.start();
123        busyLock.syncAndTest();
124        t.join();
125    }
126}
127