30 |
|
*/ |
31 |
|
static class Mutex implements Lock, java.io.Serializable { |
32 |
|
private static class Sync extends AbstractQueuedSynchronizer { |
33 |
< |
public int acquireExclusiveState(boolean isQueued, int acquires, Thread current) { |
33 |
> |
boolean isLocked() { return getState() == 1; } |
34 |
> |
|
35 |
> |
public boolean tryAcquireExclusive(int acquires) { |
36 |
|
assert acquires == 1; // Does not use multiple acquires |
37 |
< |
return state().compareAndSet(0, 1)? 0 : -1; |
37 |
> |
return compareAndSetState(0, 1); |
38 |
|
} |
39 |
|
|
40 |
< |
public boolean releaseExclusiveState(int releases) { |
41 |
< |
state().set(0); |
40 |
> |
public boolean tryReleaseExclusive(int releases) { |
41 |
> |
setState(0); |
42 |
|
return true; |
43 |
|
} |
44 |
|
|
45 |
< |
public int acquireSharedState(boolean isQueued, int acquires, Thread current) { |
46 |
< |
throw new UnsupportedOperationException(); |
45 |
< |
} |
46 |
< |
|
47 |
< |
public boolean releaseSharedState(int releases) { |
48 |
< |
throw new UnsupportedOperationException(); |
49 |
< |
} |
50 |
< |
|
51 |
< |
public void checkConditionAccess(Thread thread, boolean waiting) { |
52 |
< |
if (state().get() == 0) throw new IllegalMonitorStateException(); |
45 |
> |
public void checkConditionAccess(Thread thread) { |
46 |
> |
if (getState() == 0) throw new IllegalMonitorStateException(); |
47 |
|
} |
48 |
|
|
49 |
|
Condition newCondition() { return new ConditionObject(); } |
50 |
|
|
51 |
|
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { |
52 |
|
s.defaultReadObject(); |
53 |
< |
state().set(0); // reset to unlocked state |
53 |
> |
setState(0); // reset to unlocked state |
54 |
|
} |
55 |
+ |
|
56 |
|
} |
57 |
< |
|
57 |
> |
|
58 |
|
private final Sync sync = new Sync(); |
64 |
– |
public void lock() { sync.acquireExclusiveUninterruptibly(1); } |
59 |
|
public boolean tryLock() { |
60 |
< |
return sync.acquireExclusiveState(false, 1, null) >= 0; |
60 |
> |
return sync.tryAcquireExclusive(1); |
61 |
> |
} |
62 |
> |
public void lock() { |
63 |
> |
sync.acquireExclusiveUninterruptibly(1); |
64 |
|
} |
65 |
|
public void lockInterruptibly() throws InterruptedException { |
66 |
|
sync.acquireExclusiveInterruptibly(1); |
70 |
|
} |
71 |
|
public void unlock() { sync.releaseExclusive(1); } |
72 |
|
public Condition newCondition() { return sync.newCondition(); } |
73 |
< |
public boolean isLocked() { return sync.state().get() != 0; } |
73 |
> |
public boolean isLocked() { return sync.isLocked(); } |
74 |
|
public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } |
75 |
+ |
public boolean hasContended() { return sync.hasContended(); } |
76 |
+ |
public boolean isQueued(Thread t) { return sync.isQueued(t); } |
77 |
|
} |
78 |
|
|
79 |
|
/** |
116 |
|
} |
117 |
|
|
118 |
|
/** |
119 |
< |
* trylock on an unlocked lock succeeds |
119 |
> |
* tryLock on an unlocked lock succeeds |
120 |
|
*/ |
121 |
|
public void testTryLock() { |
122 |
|
Mutex rl = new Mutex(); |
155 |
|
} |
156 |
|
|
157 |
|
/** |
158 |
< |
* timed trylock is interruptible. |
158 |
> |
* isQueued reports whether a thread is queued. |
159 |
> |
*/ |
160 |
> |
public void testIsQueued() { |
161 |
> |
final Mutex lock = new Mutex(); |
162 |
> |
Thread t1 = new Thread(new InterruptedLockRunnable(lock)); |
163 |
> |
Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); |
164 |
> |
try { |
165 |
> |
assertFalse(lock.isQueued(t1)); |
166 |
> |
assertFalse(lock.isQueued(t2)); |
167 |
> |
lock.lock(); |
168 |
> |
t1.start(); |
169 |
> |
Thread.sleep(SHORT_DELAY_MS); |
170 |
> |
assertTrue(lock.isQueued(t1)); |
171 |
> |
t2.start(); |
172 |
> |
Thread.sleep(SHORT_DELAY_MS); |
173 |
> |
assertTrue(lock.isQueued(t1)); |
174 |
> |
assertTrue(lock.isQueued(t2)); |
175 |
> |
t1.interrupt(); |
176 |
> |
Thread.sleep(SHORT_DELAY_MS); |
177 |
> |
assertFalse(lock.isQueued(t1)); |
178 |
> |
assertTrue(lock.isQueued(t2)); |
179 |
> |
lock.unlock(); |
180 |
> |
Thread.sleep(SHORT_DELAY_MS); |
181 |
> |
assertFalse(lock.isQueued(t1)); |
182 |
> |
assertFalse(lock.isQueued(t2)); |
183 |
> |
t1.join(); |
184 |
> |
t2.join(); |
185 |
> |
} catch(Exception e){ |
186 |
> |
unexpectedException(); |
187 |
> |
} |
188 |
> |
} |
189 |
> |
|
190 |
> |
|
191 |
> |
/** |
192 |
> |
* hasContended reports whether there has been contention |
193 |
> |
*/ |
194 |
> |
public void testhasContended() { |
195 |
> |
final Mutex lock = new Mutex(); |
196 |
> |
Thread t1 = new Thread(new InterruptedLockRunnable(lock)); |
197 |
> |
Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); |
198 |
> |
try { |
199 |
> |
assertFalse(lock.hasContended()); |
200 |
> |
lock.lock(); |
201 |
> |
t1.start(); |
202 |
> |
Thread.sleep(SHORT_DELAY_MS); |
203 |
> |
assertTrue(lock.hasContended()); |
204 |
> |
t2.start(); |
205 |
> |
Thread.sleep(SHORT_DELAY_MS); |
206 |
> |
assertTrue(lock.hasContended()); |
207 |
> |
t1.interrupt(); |
208 |
> |
Thread.sleep(SHORT_DELAY_MS); |
209 |
> |
assertTrue(lock.hasContended()); |
210 |
> |
lock.unlock(); |
211 |
> |
Thread.sleep(SHORT_DELAY_MS); |
212 |
> |
assertTrue(lock.hasContended()); |
213 |
> |
t1.join(); |
214 |
> |
t2.join(); |
215 |
> |
} catch(Exception e){ |
216 |
> |
unexpectedException(); |
217 |
> |
} |
218 |
> |
} |
219 |
> |
|
220 |
> |
/** |
221 |
> |
* timed tryLock is interruptible. |
222 |
|
*/ |
223 |
|
public void testInterruptedException2() { |
224 |
|
final Mutex lock = new Mutex(); |
241 |
|
|
242 |
|
|
243 |
|
/** |
244 |
< |
* Trylock on a locked lock fails |
244 |
> |
* TryLock on a locked lock fails |
245 |
|
*/ |
246 |
|
public void testTryLockWhenLocked() { |
247 |
|
final Mutex lock = new Mutex(); |
261 |
|
} |
262 |
|
|
263 |
|
/** |
264 |
< |
* Timed trylock on a locked lock times out |
264 |
> |
* Timed tryLock on a locked lock times out |
265 |
|
*/ |
266 |
|
public void testTryLock_Timeout() { |
267 |
|
final Mutex lock = new Mutex(); |