Skip to content

Commit 80fe274

Browse files
author
Doug Lea
committed
8229442: AQS and lock classes refresh
Reviewed-by: martin
1 parent dbc8df3 commit 80fe274

14 files changed

+1842
-2769
lines changed

src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java

+505-889
Large diffs are not rendered by default.

src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java

+613-1,102
Large diffs are not rendered by default.

src/java.base/share/classes/java/util/concurrent/locks/Lock.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,8 @@
122122
* <p>All {@code Lock} implementations <em>must</em> enforce the same
123123
* memory synchronization semantics as provided by the built-in monitor
124124
* lock, as described in
125-
* <a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4">
126125
* Chapter 17 of
127-
* <cite>The Java&trade; Language Specification</cite></a>:
126+
* <cite>The Java&trade; Language Specification</cite>:
128127
* <ul>
129128
* <li>A successful {@code lock} operation has the same memory
130129
* synchronization effects as a successful <em>Lock</em> action.
@@ -162,6 +161,7 @@
162161
* @see ReentrantLock
163162
* @see Condition
164163
* @see ReadWriteLock
164+
* @jls 17.4 Memory Model
165165
*
166166
* @since 1.5
167167
* @author Doug Lea

src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java

+24-27
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,25 @@ public class LockSupport {
140140
private LockSupport() {} // Cannot be instantiated.
141141

142142
private static void setBlocker(Thread t, Object arg) {
143-
// Even though volatile, hotspot doesn't need a write barrier here.
144-
U.putReference(t, PARKBLOCKER, arg);
143+
U.putReferenceOpaque(t, PARKBLOCKER, arg);
144+
}
145+
146+
/**
147+
* Sets the object to be returned by invocations of {@link
148+
* #getBlocker getBlocker} for the current thread. This method may
149+
* be used before invoking the no-argument version of {@link
150+
* LockSupport#park() park()} from non-public objects, allowing
151+
* more helpful diagnostics, or retaining compatibility with
152+
* previous implementations of blocking methods. Previous values
153+
* of the blocker are not automatically restored after blocking.
154+
* To obtain the effects of {@code park(b}}, use {@code
155+
* setCurrentBlocker(b); park(); setCurrentBlocker(null);}
156+
*
157+
* @param blocker the blocker object
158+
* @since 14
159+
*/
160+
public static void setCurrentBlocker(Object blocker) {
161+
U.putReferenceOpaque(Thread.currentThread(), PARKBLOCKER, blocker);
145162
}
146163

147164
/**
@@ -292,7 +309,7 @@ public static void parkUntil(Object blocker, long deadline) {
292309
public static Object getBlocker(Thread t) {
293310
if (t == null)
294311
throw new NullPointerException();
295-
return U.getReferenceVolatile(t, PARKBLOCKER);
312+
return U.getReferenceOpaque(t, PARKBLOCKER);
296313
}
297314

298315
/**
@@ -393,24 +410,6 @@ public static void parkUntil(long deadline) {
393410
U.park(true, deadline);
394411
}
395412

396-
/**
397-
* Returns the pseudo-randomly initialized or updated secondary seed.
398-
* Copied from ThreadLocalRandom due to package access restrictions.
399-
*/
400-
static final int nextSecondarySeed() {
401-
int r;
402-
Thread t = Thread.currentThread();
403-
if ((r = U.getInt(t, SECONDARY)) != 0) {
404-
r ^= r << 13; // xorshift
405-
r ^= r >>> 17;
406-
r ^= r << 5;
407-
}
408-
else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)
409-
r = 1; // avoid zero
410-
U.putInt(t, SECONDARY, r);
411-
return r;
412-
}
413-
414413
/**
415414
* Returns the thread id for the given thread. We must access
416415
* this directly rather than via method Thread.getId() because
@@ -423,11 +422,9 @@ static final long getThreadId(Thread thread) {
423422

424423
// Hotspot implementation via intrinsics API
425424
private static final Unsafe U = Unsafe.getUnsafe();
426-
private static final long PARKBLOCKER = U.objectFieldOffset
427-
(Thread.class, "parkBlocker");
428-
private static final long SECONDARY = U.objectFieldOffset
429-
(Thread.class, "threadLocalRandomSecondarySeed");
430-
private static final long TID = U.objectFieldOffset
431-
(Thread.class, "tid");
425+
private static final long PARKBLOCKER
426+
= U.objectFieldOffset(Thread.class, "parkBlocker");
427+
private static final long TID
428+
= U.objectFieldOffset(Thread.class, "tid");
432429

433430
}

src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java

+87-32
Original file line numberDiff line numberDiff line change
@@ -119,39 +119,63 @@ abstract static class Sync extends AbstractQueuedSynchronizer {
119119
private static final long serialVersionUID = -5179523762034025860L;
120120

121121
/**
122-
* Performs non-fair tryLock. tryAcquire is implemented in
123-
* subclasses, but both need nonfair try for trylock method.
122+
* Performs non-fair tryLock.
124123
*/
125124
@ReservedStackAccess
126-
final boolean nonfairTryAcquire(int acquires) {
127-
final Thread current = Thread.currentThread();
125+
final boolean tryLock() {
126+
Thread current = Thread.currentThread();
128127
int c = getState();
129128
if (c == 0) {
130-
if (compareAndSetState(0, acquires)) {
129+
if (compareAndSetState(0, 1)) {
131130
setExclusiveOwnerThread(current);
132131
return true;
133132
}
134-
}
135-
else if (current == getExclusiveOwnerThread()) {
136-
int nextc = c + acquires;
137-
if (nextc < 0) // overflow
133+
} else if (getExclusiveOwnerThread() == current) {
134+
if (++c < 0) // overflow
138135
throw new Error("Maximum lock count exceeded");
139-
setState(nextc);
136+
setState(c);
140137
return true;
141138
}
142139
return false;
143140
}
144141

142+
/**
143+
* Checks for reentrancy and acquires if lock immediately
144+
* available under fair vs nonfair rules. Locking methods
145+
* perform initialTryLock check before relaying to
146+
* corresponding AQS acquire methods.
147+
*/
148+
abstract boolean initialTryLock();
149+
150+
@ReservedStackAccess
151+
final void lock() {
152+
if (!initialTryLock())
153+
acquire(1);
154+
}
155+
156+
@ReservedStackAccess
157+
final void lockInterruptibly() throws InterruptedException {
158+
if (Thread.interrupted())
159+
throw new InterruptedException();
160+
if (!initialTryLock())
161+
acquireInterruptibly(1);
162+
}
163+
164+
@ReservedStackAccess
165+
final boolean tryLockNanos(long nanos) throws InterruptedException {
166+
if (Thread.interrupted())
167+
throw new InterruptedException();
168+
return initialTryLock() || tryAcquireNanos(1, nanos);
169+
}
170+
145171
@ReservedStackAccess
146172
protected final boolean tryRelease(int releases) {
147173
int c = getState() - releases;
148-
if (Thread.currentThread() != getExclusiveOwnerThread())
174+
if (getExclusiveOwnerThread() != Thread.currentThread())
149175
throw new IllegalMonitorStateException();
150-
boolean free = false;
151-
if (c == 0) {
152-
free = true;
176+
boolean free = (c == 0);
177+
if (free)
153178
setExclusiveOwnerThread(null);
154-
}
155179
setState(c);
156180
return free;
157181
}
@@ -195,8 +219,31 @@ private void readObject(java.io.ObjectInputStream s)
195219
*/
196220
static final class NonfairSync extends Sync {
197221
private static final long serialVersionUID = 7316153563782823691L;
222+
223+
final boolean initialTryLock() {
224+
Thread current = Thread.currentThread();
225+
if (compareAndSetState(0, 1)) { // first attempt is unguarded
226+
setExclusiveOwnerThread(current);
227+
return true;
228+
} else if (getExclusiveOwnerThread() == current) {
229+
int c = getState() + 1;
230+
if (c < 0) // overflow
231+
throw new Error("Maximum lock count exceeded");
232+
setState(c);
233+
return true;
234+
} else
235+
return false;
236+
}
237+
238+
/**
239+
* Acquire for non-reentrant cases after initialTryLock prescreen
240+
*/
198241
protected final boolean tryAcquire(int acquires) {
199-
return nonfairTryAcquire(acquires);
242+
if (getState() == 0 && compareAndSetState(0, acquires)) {
243+
setExclusiveOwnerThread(Thread.currentThread());
244+
return true;
245+
}
246+
return false;
200247
}
201248
}
202249

@@ -205,26 +252,34 @@ protected final boolean tryAcquire(int acquires) {
205252
*/
206253
static final class FairSync extends Sync {
207254
private static final long serialVersionUID = -3000897897090466540L;
255+
208256
/**
209-
* Fair version of tryAcquire. Don't grant access unless
210-
* recursive call or no waiters or is first.
257+
* Acquires only if reentrant or queue is empty.
211258
*/
212-
@ReservedStackAccess
213-
protected final boolean tryAcquire(int acquires) {
214-
final Thread current = Thread.currentThread();
259+
final boolean initialTryLock() {
260+
Thread current = Thread.currentThread();
215261
int c = getState();
216262
if (c == 0) {
217-
if (!hasQueuedPredecessors() &&
218-
compareAndSetState(0, acquires)) {
263+
if (!hasQueuedThreads() && compareAndSetState(0, 1)) {
219264
setExclusiveOwnerThread(current);
220265
return true;
221266
}
222-
}
223-
else if (current == getExclusiveOwnerThread()) {
224-
int nextc = c + acquires;
225-
if (nextc < 0)
267+
} else if (getExclusiveOwnerThread() == current) {
268+
if (++c < 0) // overflow
226269
throw new Error("Maximum lock count exceeded");
227-
setState(nextc);
270+
setState(c);
271+
return true;
272+
}
273+
return false;
274+
}
275+
276+
/**
277+
* Acquires only if thread is first waiter or empty
278+
*/
279+
protected final boolean tryAcquire(int acquires) {
280+
if (getState() == 0 && !hasQueuedPredecessors() &&
281+
compareAndSetState(0, acquires)) {
282+
setExclusiveOwnerThread(Thread.currentThread());
228283
return true;
229284
}
230285
return false;
@@ -264,7 +319,7 @@ public ReentrantLock(boolean fair) {
264319
* at which time the lock hold count is set to one.
265320
*/
266321
public void lock() {
267-
sync.acquire(1);
322+
sync.lock();
268323
}
269324

270325
/**
@@ -314,7 +369,7 @@ public void lock() {
314369
* @throws InterruptedException if the current thread is interrupted
315370
*/
316371
public void lockInterruptibly() throws InterruptedException {
317-
sync.acquireInterruptibly(1);
372+
sync.lockInterruptibly();
318373
}
319374

320375
/**
@@ -344,7 +399,7 @@ public void lockInterruptibly() throws InterruptedException {
344399
* thread; and {@code false} otherwise
345400
*/
346401
public boolean tryLock() {
347-
return sync.nonfairTryAcquire(1);
402+
return sync.tryLock();
348403
}
349404

350405
/**
@@ -421,7 +476,7 @@ public boolean tryLock() {
421476
*/
422477
public boolean tryLock(long timeout, TimeUnit unit)
423478
throws InterruptedException {
424-
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
479+
return sync.tryLockNanos(unit.toNanos(timeout));
425480
}
426481

427482
/**

0 commit comments

Comments
 (0)