From 4a06ae967d4576beda20646b168ea3f2ee3928df Mon Sep 17 00:00:00 2001 From: dl Date: Fri, 26 Oct 2012 21:34:24 +0100 Subject: [PATCH] 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012 Reviewed-by: chegar, dholmes --- .../concurrent/AbstractExecutorService.java | 24 ++-- .../java/util/concurrent/BlockingQueue.java | 5 +- .../concurrent/BrokenBarrierException.java | 1 - .../util/concurrent/CompletionService.java | 2 - .../concurrent/ConcurrentLinkedDeque.java | 11 +- .../concurrent/ConcurrentLinkedQueue.java | 11 +- .../java/util/concurrent/ConcurrentMap.java | 46 ++++--- .../concurrent/ConcurrentNavigableMap.java | 1 - .../concurrent/ConcurrentSkipListMap.java | 10 +- .../concurrent/ConcurrentSkipListSet.java | 2 +- .../util/concurrent/CopyOnWriteArrayList.java | 41 +++---- .../util/concurrent/CopyOnWriteArraySet.java | 7 +- .../java/util/concurrent/CountDownLatch.java | 15 +-- .../java/util/concurrent/CyclicBarrier.java | 49 ++++---- .../classes/java/util/concurrent/Delayed.java | 2 - .../util/concurrent/ExecutionException.java | 8 +- .../java/util/concurrent/Executor.java | 20 +-- .../java/util/concurrent/ExecutorService.java | 14 +-- .../java/util/concurrent/Executors.java | 6 +- .../classes/java/util/concurrent/Future.java | 12 +- .../util/concurrent/LinkedBlockingDeque.java | 14 +-- .../util/concurrent/LinkedBlockingQueue.java | 20 +-- .../util/concurrent/LinkedTransferQueue.java | 15 +-- .../java/util/concurrent/RecursiveAction.java | 36 ++++-- .../RejectedExecutionException.java | 4 +- .../concurrent/ScheduledExecutorService.java | 2 - .../ScheduledThreadPoolExecutor.java | 38 +++--- .../java/util/concurrent/Semaphore.java | 16 +-- .../util/concurrent/SynchronousQueue.java | 41 +++---- .../java/util/concurrent/ThreadFactory.java | 5 +- .../java/util/concurrent/TimeUnit.java | 14 +-- .../util/concurrent/atomic/AtomicInteger.java | 1 - .../atomic/AtomicIntegerFieldUpdater.java | 8 +- .../util/concurrent/atomic/AtomicLong.java | 1 - .../atomic/AtomicLongFieldUpdater.java | 8 +- .../concurrent/atomic/AtomicReference.java | 2 +- .../atomic/AtomicReferenceArray.java | 7 +- .../atomic/AtomicReferenceFieldUpdater.java | 30 ++--- .../util/concurrent/atomic/package-info.java | 35 ++++-- .../locks/AbstractQueuedLongSynchronizer.java | 85 ++++++------- .../locks/AbstractQueuedSynchronizer.java | 96 ++++++--------- .../java/util/concurrent/locks/Condition.java | 9 +- .../java/util/concurrent/locks/Lock.java | 45 +++---- .../util/concurrent/locks/LockSupport.java | 10 +- .../util/concurrent/locks/ReentrantLock.java | 38 +++--- .../locks/ReentrantReadWriteLock.java | 115 +++++++++--------- .../java/util/concurrent/package-info.java | 7 +- 47 files changed, 456 insertions(+), 533 deletions(-) diff --git a/src/share/classes/java/util/concurrent/AbstractExecutorService.java b/src/share/classes/java/util/concurrent/AbstractExecutorService.java index bac93ab3b..fdf8b4375 100644 --- a/src/share/classes/java/util/concurrent/AbstractExecutorService.java +++ b/src/share/classes/java/util/concurrent/AbstractExecutorService.java @@ -137,7 +137,7 @@ public abstract class AbstractExecutorService implements ExecutorService { * the main mechanics of invokeAny. */ private T doInvokeAny(Collection> tasks, - boolean timed, long nanos) + boolean timed, long nanos) throws InterruptedException, ExecutionException, TimeoutException { if (tasks == null) throw new NullPointerException(); @@ -158,7 +158,7 @@ public abstract class AbstractExecutorService implements ExecutorService { // Record exceptions so that if we fail to obtain any // result, we can throw the last exception we got. ExecutionException ee = null; - long lastTime = timed ? System.nanoTime() : 0; + final long deadline = timed ? System.nanoTime() + nanos : 0L; Iterator> it = tasks.iterator(); // Start one task for sure; the rest incrementally @@ -180,9 +180,7 @@ public abstract class AbstractExecutorService implements ExecutorService { f = ecs.poll(nanos, TimeUnit.NANOSECONDS); if (f == null) throw new TimeoutException(); - long now = System.nanoTime(); - nanos -= now - lastTime; - lastTime = now; + nanos = deadline - System.nanoTime(); } else f = ecs.take(); @@ -258,7 +256,7 @@ public abstract class AbstractExecutorService implements ExecutorService { public List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException { - if (tasks == null || unit == null) + if (tasks == null) throw new NullPointerException(); long nanos = unit.toNanos(timeout); List> futures = new ArrayList>(tasks.size()); @@ -267,23 +265,21 @@ public abstract class AbstractExecutorService implements ExecutorService { for (Callable t : tasks) futures.add(newTaskFor(t)); - long lastTime = System.nanoTime(); + final long deadline = System.nanoTime() + nanos; // Interleave time checks and calls to execute in case // executor doesn't have any/much parallelism. Iterator> it = futures.iterator(); while (it.hasNext()) { execute((Runnable)(it.next())); - long now = System.nanoTime(); - nanos -= now - lastTime; - lastTime = now; - if (nanos <= 0) + nanos = deadline - System.nanoTime(); + if (nanos <= 0L) return futures; } for (Future f : futures) { if (!f.isDone()) { - if (nanos <= 0) + if (nanos <= 0L) return futures; try { f.get(nanos, TimeUnit.NANOSECONDS); @@ -292,9 +288,7 @@ public abstract class AbstractExecutorService implements ExecutorService { } catch (TimeoutException toe) { return futures; } - long now = System.nanoTime(); - nanos -= now - lastTime; - lastTime = now; + nanos = deadline - System.nanoTime(); } } done = true; diff --git a/src/share/classes/java/util/concurrent/BlockingQueue.java b/src/share/classes/java/util/concurrent/BlockingQueue.java index 4511d27ef..bb5eb6033 100644 --- a/src/share/classes/java/util/concurrent/BlockingQueue.java +++ b/src/share/classes/java/util/concurrent/BlockingQueue.java @@ -127,7 +127,7 @@ import java.util.Queue; * Usage example, based on a typical producer-consumer scenario. * Note that a BlockingQueue can safely be used with multiple * producers and multiple consumers. - *
+ *  
 {@code
  * class Producer implements Runnable {
  *   private final BlockingQueue queue;
  *   Producer(BlockingQueue q) { queue = q; }
@@ -160,8 +160,7 @@ import java.util.Queue;
  *     new Thread(c1).start();
  *     new Thread(c2).start();
  *   }
- * }
- * 
+ * }}
* *

Memory consistency effects: As with other concurrent * collections, actions in a thread prior to placing an object into a diff --git a/src/share/classes/java/util/concurrent/BrokenBarrierException.java b/src/share/classes/java/util/concurrent/BrokenBarrierException.java index 9d2a9f4b4..2c8f7e339 100644 --- a/src/share/classes/java/util/concurrent/BrokenBarrierException.java +++ b/src/share/classes/java/util/concurrent/BrokenBarrierException.java @@ -44,7 +44,6 @@ package java.util.concurrent; * * @since 1.5 * @author Doug Lea - * */ public class BrokenBarrierException extends Exception { private static final long serialVersionUID = 7117394618823254244L; diff --git a/src/share/classes/java/util/concurrent/CompletionService.java b/src/share/classes/java/util/concurrent/CompletionService.java index 5a807c5ef..78d09f302 100644 --- a/src/share/classes/java/util/concurrent/CompletionService.java +++ b/src/share/classes/java/util/concurrent/CompletionService.java @@ -57,7 +57,6 @@ package java.util.concurrent; * happen-before * actions taken by that task, which in turn happen-before * actions following a successful return from the corresponding {@code take()}. - * */ public interface CompletionService { /** @@ -98,7 +97,6 @@ public interface CompletionService { */ Future take() throws InterruptedException; - /** * Retrieves and removes the Future representing the next * completed task or null if none are present. diff --git a/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java b/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java index c26e371f9..146934af4 100644 --- a/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java +++ b/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java @@ -90,7 +90,6 @@ import java.util.Queue; * @author Martin Buchholz * @param the type of elements held in this collection */ - public class ConcurrentLinkedDeque extends AbstractCollection implements Deque, java.io.Serializable { @@ -1250,8 +1249,7 @@ public class ConcurrentLinkedDeque * The following code can be used to dump the deque into a newly * allocated array of {@code String}: * - *

-     *     String[] y = x.toArray(new String[0]);
+ *
 {@code String[] y = x.toArray(new String[0]);}
* * Note that {@code toArray(new Object[0])} is identical in function to * {@code toArray()}. @@ -1388,11 +1386,10 @@ public class ConcurrentLinkedDeque } /** - * Saves the state to a stream (that is, serializes it). + * Saves this deque to a stream (that is, serializes it). * * @serialData All of the elements (each an {@code E}) in * the proper order, followed by a null - * @param s the stream */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { @@ -1412,8 +1409,7 @@ public class ConcurrentLinkedDeque } /** - * Reconstitutes the instance from a stream (that is, deserializes it). - * @param s the stream + * Reconstitutes this deque from a stream (that is, deserializes it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { @@ -1436,7 +1432,6 @@ public class ConcurrentLinkedDeque initHeadTail(h, t); } - private boolean casHead(Node cmp, Node val) { return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val); } diff --git a/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java b/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java index dfac05c6d..abf12c597 100644 --- a/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -98,7 +98,6 @@ import java.util.Queue; * @since 1.5 * @author Doug Lea * @param the type of elements held in this collection - * */ public class ConcurrentLinkedQueue extends AbstractQueue implements Queue, java.io.Serializable { @@ -247,7 +246,6 @@ public class ConcurrentLinkedQueue extends AbstractQueue */ private transient volatile Node tail; - /** * Creates a {@code ConcurrentLinkedQueue} that is initially empty. */ @@ -609,8 +607,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue * The following code can be used to dump the queue into a newly * allocated array of {@code String}: * - *
-     *     String[] y = x.toArray(new String[0]);
+ *
 {@code String[] y = x.toArray(new String[0]);}
* * Note that {@code toArray(new Object[0])} is identical in function to * {@code toArray()}. @@ -747,11 +744,10 @@ public class ConcurrentLinkedQueue extends AbstractQueue } /** - * Saves the state to a stream (that is, serializes it). + * Saves this queue to a stream (that is, serializes it). * * @serialData All of the elements (each an {@code E}) in * the proper order, followed by a null - * @param s the stream */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { @@ -771,8 +767,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue } /** - * Reconstitutes the instance from a stream (that is, deserializes it). - * @param s the stream + * Reconstitutes this queue from a stream (that is, deserializes it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { diff --git a/src/share/classes/java/util/concurrent/ConcurrentMap.java b/src/share/classes/java/util/concurrent/ConcurrentMap.java index 4434c0563..a725db6e6 100644 --- a/src/share/classes/java/util/concurrent/ConcurrentMap.java +++ b/src/share/classes/java/util/concurrent/ConcurrentMap.java @@ -61,11 +61,12 @@ public interface ConcurrentMap extends Map { * If the specified key is not already associated * with a value, associate it with the given value. * This is equivalent to - *
-     *   if (!map.containsKey(key))
-     *       return map.put(key, value);
-     *   else
-     *       return map.get(key);
+ *
 {@code
+     * if (!map.containsKey(key))
+     *   return map.put(key, value);
+     * else
+     *   return map.get(key);}
+ * * except that the action is performed atomically. * * @param key key with which the specified value is to be associated @@ -83,18 +84,19 @@ public interface ConcurrentMap extends Map { * and this map does not permit null keys or values * @throws IllegalArgumentException if some property of the specified key * or value prevents it from being stored in this map - * */ V putIfAbsent(K key, V value); /** * Removes the entry for a key only if currently mapped to a given value. * This is equivalent to - *
-     *   if (map.containsKey(key) && map.get(key).equals(value)) {
-     *       map.remove(key);
-     *       return true;
-     *   } else return false;
+ *
 {@code
+     * if (map.containsKey(key) && map.get(key).equals(value)) {
+     *   map.remove(key);
+     *   return true;
+     * } else
+     *   return false;}
+ * * except that the action is performed atomically. * * @param key key with which the specified value is associated @@ -114,11 +116,13 @@ public interface ConcurrentMap extends Map { /** * Replaces the entry for a key only if currently mapped to a given value. * This is equivalent to - *
-     *   if (map.containsKey(key) && map.get(key).equals(oldValue)) {
-     *       map.put(key, newValue);
-     *       return true;
-     *   } else return false;
+ *
 {@code
+     * if (map.containsKey(key) && map.get(key).equals(oldValue)) {
+     *   map.put(key, newValue);
+     *   return true;
+     * } else
+     *   return false;}
+ * * except that the action is performed atomically. * * @param key key with which the specified value is associated @@ -139,10 +143,12 @@ public interface ConcurrentMap extends Map { /** * Replaces the entry for a key only if currently mapped to some value. * This is equivalent to - *
-     *   if (map.containsKey(key)) {
-     *       return map.put(key, value);
-     *   } else return null;
+ *
 {@code
+     * if (map.containsKey(key)) {
+     *   return map.put(key, value);
+     * } else
+     *   return null;}
+ * * except that the action is performed atomically. * * @param key key with which the specified value is associated diff --git a/src/share/classes/java/util/concurrent/ConcurrentNavigableMap.java b/src/share/classes/java/util/concurrent/ConcurrentNavigableMap.java index df5bb31d1..1d096f0c5 100644 --- a/src/share/classes/java/util/concurrent/ConcurrentNavigableMap.java +++ b/src/share/classes/java/util/concurrent/ConcurrentNavigableMap.java @@ -67,7 +67,6 @@ public interface ConcurrentNavigableMap */ ConcurrentNavigableMap headMap(K toKey, boolean inclusive); - /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} diff --git a/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java index fdf83d1cc..cd93e2118 100644 --- a/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +++ b/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java @@ -1507,7 +1507,7 @@ public class ConcurrentSkipListMap extends AbstractMap /* ---------------- Serialization -------------- */ /** - * Saves the state of this map to a stream (that is, serializes it). + * Saves this map to a stream (that is, serializes it). * * @serialData The key (Object) and value (Object) for each * key-value mapping represented by the map, followed by @@ -1532,9 +1532,7 @@ public class ConcurrentSkipListMap extends AbstractMap } /** - * Reconstitutes the map from a stream (that is, deserializes it). - * - * @param s the stream + * Reconstitutes this map from a stream (that is, deserializes it). */ private void readObject(final java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { @@ -2342,7 +2340,7 @@ public class ConcurrentSkipListMap extends AbstractMap Collection c = (Collection) o; try { return containsAll(c) && c.containsAll(this); - } catch (ClassCastException unused) { + } catch (ClassCastException unused) { return false; } catch (NullPointerException unused) { return false; @@ -2451,7 +2449,7 @@ public class ConcurrentSkipListMap extends AbstractMap Collection c = (Collection) o; try { return containsAll(c) && c.containsAll(this); - } catch (ClassCastException unused) { + } catch (ClassCastException unused) { return false; } catch (NullPointerException unused) { return false; diff --git a/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java b/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java index b250c1a51..8214b37c4 100644 --- a/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java +++ b/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java @@ -298,7 +298,7 @@ public class ConcurrentSkipListSet Collection c = (Collection) o; try { return containsAll(c) && c.containsAll(this); - } catch (ClassCastException unused) { + } catch (ClassCastException unused) { return false; } catch (NullPointerException unused) { return false; diff --git a/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index e61dd7921..5621c907c 100644 --- a/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -35,7 +35,7 @@ package java.util.concurrent; import java.util.*; -import java.util.concurrent.locks.*; +import java.util.concurrent.locks.ReentrantLock; /** * A thread-safe variant of {@link java.util.ArrayList} in which all mutative @@ -152,7 +152,7 @@ public class CopyOnWriteArrayList } /** - * Test for equality, coping with nulls. + * Tests for equality, coping with nulls. */ private static boolean eq(Object o1, Object o2) { return (o1 == null ? o2 == null : o1.equals(o2)); @@ -333,8 +333,7 @@ public class CopyOnWriteArrayList * The following code can be used to dump the list into a newly * allocated array of String: * - *
-     *     String[] y = x.toArray(new String[0]);
+ *
 {@code String[] y = x.toArray(new String[0]);}
* * Note that toArray(new Object[0]) is identical in function to * toArray(). @@ -548,9 +547,9 @@ public class CopyOnWriteArrayList * @param fromIndex index of first element to be removed * @param toIndex index after last element to be removed * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range - * ({@code{fromIndex < 0 || toIndex > size() || toIndex < fromIndex}) + * ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex}) */ - private void removeRange(int fromIndex, int toIndex) { + void removeRange(int fromIndex, int toIndex) { final ReentrantLock lock = this.lock; lock.lock(); try { @@ -576,7 +575,7 @@ public class CopyOnWriteArrayList } /** - * Append the element if not present. + * Appends the element, if not present. * * @param e element to be added to this list, if absent * @return true if the element was added @@ -641,6 +640,7 @@ public class CopyOnWriteArrayList * @see #remove(Object) */ public boolean removeAll(Collection c) { + if (c == null) throw new NullPointerException(); final ReentrantLock lock = this.lock; lock.lock(); try { @@ -683,6 +683,7 @@ public class CopyOnWriteArrayList * @see #remove(Object) */ public boolean retainAll(Collection c) { + if (c == null) throw new NullPointerException(); final ReentrantLock lock = this.lock; lock.lock(); try { @@ -837,15 +838,14 @@ public class CopyOnWriteArrayList } /** - * Saves the state of the list to a stream (that is, serializes it). + * Saves this list to a stream (that is, serializes it). * * @serialData The length of the array backing the list is emitted * (int), followed by all of its elements (each an Object) * in the proper order. - * @param s the stream */ private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException{ + throws java.io.IOException { s.defaultWriteObject(); @@ -859,9 +859,7 @@ public class CopyOnWriteArrayList } /** - * Reconstitutes the list from a stream (that is, deserializes it). - * - * @param s the stream + * Reconstitutes this list from a stream (that is, deserializes it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { @@ -1266,17 +1264,14 @@ public class CopyOnWriteArrayList private static class COWSubListIterator implements ListIterator { - private final ListIterator i; - private final int index; + private final ListIterator it; private final int offset; private final int size; - COWSubListIterator(List l, int index, int offset, - int size) { - this.index = index; + COWSubListIterator(List l, int index, int offset, int size) { this.offset = offset; this.size = size; - i = l.listIterator(index+offset); + it = l.listIterator(index+offset); } public boolean hasNext() { @@ -1285,7 +1280,7 @@ public class CopyOnWriteArrayList public E next() { if (hasNext()) - return i.next(); + return it.next(); else throw new NoSuchElementException(); } @@ -1296,17 +1291,17 @@ public class CopyOnWriteArrayList public E previous() { if (hasPrevious()) - return i.previous(); + return it.previous(); else throw new NoSuchElementException(); } public int nextIndex() { - return i.nextIndex() - offset; + return it.nextIndex() - offset; } public int previousIndex() { - return i.previousIndex() - offset; + return it.previousIndex() - offset; } public void remove() { diff --git a/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java b/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java index d51804822..da3c98563 100644 --- a/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java +++ b/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java @@ -189,8 +189,7 @@ public class CopyOnWriteArraySet extends AbstractSet * The following code can be used to dump the set into a newly allocated * array of String: * - *
-     *     String[] y = x.toArray(new String[0]);
+ *
 {@code String[] y = x.toArray(new String[0]);}
* * Note that toArray(new Object[0]) is identical in function to * toArray(). @@ -384,9 +383,9 @@ public class CopyOnWriteArraySet extends AbstractSet } /** - * Test for equality, coping with nulls. + * Tests for equality, coping with nulls. */ private static boolean eq(Object o1, Object o2) { - return (o1 == null ? o2 == null : o1.equals(o2)); + return (o1 == null) ? o2 == null : o1.equals(o2); } } diff --git a/src/share/classes/java/util/concurrent/CountDownLatch.java b/src/share/classes/java/util/concurrent/CountDownLatch.java index 187b1f235..055eb1137 100644 --- a/src/share/classes/java/util/concurrent/CountDownLatch.java +++ b/src/share/classes/java/util/concurrent/CountDownLatch.java @@ -34,8 +34,7 @@ */ package java.util.concurrent; -import java.util.concurrent.locks.*; -import java.util.concurrent.atomic.*; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; /** * A synchronization aid that allows one or more threads to wait until @@ -73,7 +72,7 @@ import java.util.concurrent.atomic.*; * until all workers have completed. * * - *
+ *  
 {@code
  * class Driver { // ...
  *   void main() throws InterruptedException {
  *     CountDownLatch startSignal = new CountDownLatch(1);
@@ -105,9 +104,7 @@ import java.util.concurrent.atomic.*;
  *   }
  *
  *   void doWork() { ... }
- * }
- *
- * 
+ * }}
* *

Another typical usage would be to divide a problem into N parts, * describe each part with a Runnable that executes that portion and @@ -116,7 +113,7 @@ import java.util.concurrent.atomic.*; * will be able to pass through await. (When threads must repeatedly * count down in this way, instead use a {@link CyclicBarrier}.) * - *

+ *  
 {@code
  * class Driver2 { // ...
  *   void main() throws InterruptedException {
  *     CountDownLatch doneSignal = new CountDownLatch(N);
@@ -144,9 +141,7 @@ import java.util.concurrent.atomic.*;
  *   }
  *
  *   void doWork() { ... }
- * }
- *
- * 
+ * }}
* *

Memory consistency effects: Until the count reaches * zero, actions in a thread prior to calling diff --git a/src/share/classes/java/util/concurrent/CyclicBarrier.java b/src/share/classes/java/util/concurrent/CyclicBarrier.java index 01d64b116..eb25879db 100644 --- a/src/share/classes/java/util/concurrent/CyclicBarrier.java +++ b/src/share/classes/java/util/concurrent/CyclicBarrier.java @@ -34,7 +34,8 @@ */ package java.util.concurrent; -import java.util.concurrent.locks.*; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; /** * A synchronization aid that allows a set of threads to all wait for @@ -52,7 +53,8 @@ import java.util.concurrent.locks.*; * *

Sample usage: Here is an example of * using a barrier in a parallel decomposition design: - *

+ *
+ *  
 {@code
  * class Solver {
  *   final int N;
  *   final float[][] data;
@@ -90,8 +92,8 @@ import java.util.concurrent.locks.*;
  *
  *     waitUntilDone();
  *   }
- * }
- * 
+ * }}
+ * * Here, each worker thread processes a row of the matrix then waits at the * barrier until all rows have been processed. When all rows are processed * the supplied {@link Runnable} barrier action is executed and merges the @@ -105,9 +107,10 @@ import java.util.concurrent.locks.*; * {@link #await} returns the arrival index of that thread at the barrier. * You can then choose which thread should execute the barrier action, for * example: - *
  if (barrier.await() == 0) {
- *     // log the completion of this iteration
- *   }
+ *
 {@code
+ * if (barrier.await() == 0) {
+ *   // log the completion of this iteration
+ * }}
* *

The CyclicBarrier uses an all-or-none breakage model * for failed synchronization attempts: If a thread leaves a barrier @@ -204,21 +207,21 @@ public class CyclicBarrier { throw new InterruptedException(); } - int index = --count; - if (index == 0) { // tripped - boolean ranAction = false; - try { - final Runnable command = barrierCommand; - if (command != null) - command.run(); - ranAction = true; - nextGeneration(); - return 0; - } finally { - if (!ranAction) - breakBarrier(); - } - } + int index = --count; + if (index == 0) { // tripped + boolean ranAction = false; + try { + final Runnable command = barrierCommand; + if (command != null) + command.run(); + ranAction = true; + nextGeneration(); + return 0; + } finally { + if (!ranAction) + breakBarrier(); + } + } // loop until tripped, broken, interrupted, or timed out for (;;) { @@ -354,7 +357,7 @@ public class CyclicBarrier { try { return dowait(false, 0L); } catch (TimeoutException toe) { - throw new Error(toe); // cannot happen; + throw new Error(toe); // cannot happen } } diff --git a/src/share/classes/java/util/concurrent/Delayed.java b/src/share/classes/java/util/concurrent/Delayed.java index d77564121..8b185e1d7 100644 --- a/src/share/classes/java/util/concurrent/Delayed.java +++ b/src/share/classes/java/util/concurrent/Delayed.java @@ -35,8 +35,6 @@ package java.util.concurrent; -import java.util.*; - /** * A mix-in style interface for marking objects that should be * acted upon after a given delay. diff --git a/src/share/classes/java/util/concurrent/ExecutionException.java b/src/share/classes/java/util/concurrent/ExecutionException.java index fc2b1e899..f5bfa7f30 100644 --- a/src/share/classes/java/util/concurrent/ExecutionException.java +++ b/src/share/classes/java/util/concurrent/ExecutionException.java @@ -79,11 +79,9 @@ public class ExecutionException extends Exception { /** * Constructs an ExecutionException with the specified cause. - * The detail message is set to: - *

-     *  (cause == null ? null : cause.toString())
- * (which typically contains the class and detail message of - * cause). + * The detail message is set to {@code (cause == null ? null : + * cause.toString())} (which typically contains the class and + * detail message of {@code cause}). * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method) diff --git a/src/share/classes/java/util/concurrent/Executor.java b/src/share/classes/java/util/concurrent/Executor.java index 6b4574a63..09b9ac367 100644 --- a/src/share/classes/java/util/concurrent/Executor.java +++ b/src/share/classes/java/util/concurrent/Executor.java @@ -56,23 +56,23 @@ package java.util.concurrent; * executor can run the submitted task immediately in the caller's * thread: * - *
+ *  
 {@code
  * class DirectExecutor implements Executor {
- *     public void execute(Runnable r) {
- *         r.run();
- *     }
- * }
+ * public void execute(Runnable r) { + * r.run(); + * } + * }}
* * More typically, tasks are executed in some thread other * than the caller's thread. The executor below spawns a new thread * for each task. * - *
+ *  
 {@code
  * class ThreadPerTaskExecutor implements Executor {
- *     public void execute(Runnable r) {
- *         new Thread(r).start();
- *     }
- * }
+ * public void execute(Runnable r) { + * new Thread(r).start(); + * } + * }}
* * Many Executor implementations impose some sort of * limitation on how and when tasks are scheduled. The executor below diff --git a/src/share/classes/java/util/concurrent/ExecutorService.java b/src/share/classes/java/util/concurrent/ExecutorService.java index f1ab3275e..2340d2a0b 100644 --- a/src/share/classes/java/util/concurrent/ExecutorService.java +++ b/src/share/classes/java/util/concurrent/ExecutorService.java @@ -36,8 +36,6 @@ package java.util.concurrent; import java.util.List; import java.util.Collection; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; /** * An {@link Executor} that provides methods to manage termination and @@ -73,7 +71,7 @@ import java.security.PrivilegedExceptionAction; * pool service incoming requests. It uses the preconfigured {@link * Executors#newFixedThreadPool} factory method: * - *
+ *  
 {@code
  * class NetworkService implements Runnable {
  *   private final ServerSocket serverSocket;
  *   private final ExecutorService pool;
@@ -101,14 +99,13 @@ import java.security.PrivilegedExceptionAction;
  *   public void run() {
  *     // read and service request on socket
  *   }
- * }
- * 
+ * }}
* * The following method shuts down an ExecutorService in two phases, * first by calling shutdown to reject incoming tasks, and then * calling shutdownNow, if necessary, to cancel any lingering tasks: * - *
+ *  
 {@code
  * void shutdownAndAwaitTermination(ExecutorService pool) {
  *   pool.shutdown(); // Disable new tasks from being submitted
  *   try {
@@ -125,8 +122,7 @@ import java.security.PrivilegedExceptionAction;
  *     // Preserve interrupt status
  *     Thread.currentThread().interrupt();
  *   }
- * }
- * 
+ * }}
* *

Memory consistency effects: Actions in a thread prior to the * submission of a {@code Runnable} or {@code Callable} task to an @@ -214,7 +210,6 @@ public interface ExecutorService extends Executor { boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; - /** * Submits a value-returning task for execution and returns a * Future representing the pending results of the task. The @@ -286,7 +281,6 @@ public interface ExecutorService extends Executor { * @throws RejectedExecutionException if any task cannot be * scheduled for execution */ - List> invokeAll(Collection> tasks) throws InterruptedException; diff --git a/src/share/classes/java/util/concurrent/Executors.java b/src/share/classes/java/util/concurrent/Executors.java index 4ff714184..723dc3209 100644 --- a/src/share/classes/java/util/concurrent/Executors.java +++ b/src/share/classes/java/util/concurrent/Executors.java @@ -686,16 +686,16 @@ public class Executors { super(executor); e = executor; } - public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { + public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { return e.schedule(command, delay, unit); } public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { return e.schedule(callable, delay, unit); } - public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { + public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { return e.scheduleAtFixedRate(command, initialDelay, period, unit); } - public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { + public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { return e.scheduleWithFixedDelay(command, initialDelay, delay, unit); } } diff --git a/src/share/classes/java/util/concurrent/Future.java b/src/share/classes/java/util/concurrent/Future.java index 2aab18ed3..74ded1836 100644 --- a/src/share/classes/java/util/concurrent/Future.java +++ b/src/share/classes/java/util/concurrent/Future.java @@ -76,12 +76,12 @@ package java.util.concurrent; * implements Runnable, and so may be executed by an Executor. * For example, the above construction with submit could be replaced by: *

 {@code
- *     FutureTask future =
- *       new FutureTask(new Callable() {
- *         public String call() {
- *           return searcher.search(target);
- *       }});
- *     executor.execute(future);}
+ * FutureTask future = + * new FutureTask(new Callable() { + * public String call() { + * return searcher.search(target); + * }}); + * executor.execute(future);} * *

Memory consistency effects: Actions taken by the asynchronous computation * happen-before diff --git a/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java index 60a18d0db..b79bc9444 100644 --- a/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -73,7 +73,7 @@ import java.util.concurrent.locks.ReentrantLock; */ public class LinkedBlockingDeque extends AbstractQueue - implements BlockingDeque, java.io.Serializable { + implements BlockingDeque, java.io.Serializable { /* * Implemented as a simple doubly-linked list protected by a @@ -922,8 +922,7 @@ public class LinkedBlockingDeque * The following code can be used to dump the deque into a newly * allocated array of {@code String}: * - *

-     *     String[] y = x.toArray(new String[0]);
+ *
 {@code String[] y = x.toArray(new String[0]);}
* * Note that {@code toArray(new Object[0])} is identical in function to * {@code toArray()}. @@ -1045,7 +1044,7 @@ public class LinkedBlockingDeque /** * The next node to return in next() */ - Node next; + Node next; /** * nextItem holds on to item fields because once we claim that @@ -1153,11 +1152,10 @@ public class LinkedBlockingDeque } /** - * Save the state of this deque to a stream (that is, serialize it). + * Saves this deque to a stream (that is, serializes it). * * @serialData The capacity (int), followed by elements (each an * {@code Object}) in the proper order, followed by a null - * @param s the stream */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { @@ -1177,9 +1175,7 @@ public class LinkedBlockingDeque } /** - * Reconstitute this deque from a stream (that is, - * deserialize it). - * @param s the stream + * Reconstitutes this deque from a stream (that is, deserializes it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { diff --git a/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java b/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java index d1a6d5a0b..e95e0a32a 100644 --- a/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java +++ b/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java @@ -73,7 +73,6 @@ import java.util.NoSuchElementException; * @since 1.5 * @author Doug Lea * @param the type of elements held in this collection - * */ public class LinkedBlockingQueue extends AbstractQueue implements BlockingQueue, java.io.Serializable { @@ -135,13 +134,13 @@ public class LinkedBlockingQueue extends AbstractQueue private final int capacity; /** Current number of elements */ - private final AtomicInteger count = new AtomicInteger(0); + private final AtomicInteger count = new AtomicInteger(); /** * Head of linked list. * Invariant: head.item == null */ - private transient Node head; + transient Node head; /** * Tail of linked list. @@ -291,7 +290,6 @@ public class LinkedBlockingQueue extends AbstractQueue } } - // this doc comment is overridden to remove the reference to collections // greater in size than Integer.MAX_VALUE /** @@ -430,7 +428,6 @@ public class LinkedBlockingQueue extends AbstractQueue return c >= 0; } - public E take() throws InterruptedException { E x; int c = -1; @@ -630,8 +627,7 @@ public class LinkedBlockingQueue extends AbstractQueue * The following code can be used to dump the queue into a newly * allocated array of {@code String}: * - *
-     *     String[] y = x.toArray(new String[0]);
+ *
 {@code String[] y = x.toArray(new String[0]);}
* * Note that {@code toArray(new Object[0])} is identical in function to * {@code toArray()}. @@ -777,7 +773,7 @@ public class LinkedBlockingQueue extends AbstractQueue * @return an iterator over the elements in this queue in proper sequence */ public Iterator iterator() { - return new Itr(); + return new Itr(); } private class Itr implements Iterator { @@ -860,12 +856,11 @@ public class LinkedBlockingQueue extends AbstractQueue } /** - * Save the state to a stream (that is, serialize it). + * Saves this queue to a stream (that is, serializes it). * * @serialData The capacity is emitted (int), followed by all of * its elements (each an {@code Object}) in the proper order, * followed by a null - * @param s the stream */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { @@ -887,10 +882,7 @@ public class LinkedBlockingQueue extends AbstractQueue } /** - * Reconstitute this queue instance from a stream (that is, - * deserialize it). - * - * @param s the stream + * Reconstitutes this queue from a stream (that is, deserializes it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { diff --git a/src/share/classes/java/util/concurrent/LinkedTransferQueue.java b/src/share/classes/java/util/concurrent/LinkedTransferQueue.java index 171523f16..6b6e46a92 100644 --- a/src/share/classes/java/util/concurrent/LinkedTransferQueue.java +++ b/src/share/classes/java/util/concurrent/LinkedTransferQueue.java @@ -695,7 +695,7 @@ public class LinkedTransferQueue extends AbstractQueue * @return matched item, or e if unmatched on interrupt or timeout */ private E awaitMatch(Node s, Node pred, E e, boolean timed, long nanos) { - long lastTime = timed ? System.nanoTime() : 0L; + final long deadline = timed ? System.nanoTime() + nanos : 0L; Thread w = Thread.currentThread(); int spins = -1; // initialized after first item and cancel checks ThreadLocalRandom randomYields = null; // bound if needed @@ -726,10 +726,9 @@ public class LinkedTransferQueue extends AbstractQueue s.waiter = w; // request unpark then recheck } else if (timed) { - long now = System.nanoTime(); - if ((nanos -= now - lastTime) > 0) + nanos = deadline - System.nanoTime(); + if (nanos > 0L) LockSupport.parkNanos(this, nanos); - lastTime = now; } else { LockSupport.park(this); @@ -1294,11 +1293,10 @@ public class LinkedTransferQueue extends AbstractQueue } /** - * Saves the state to a stream (that is, serializes it). + * Saves this queue to a stream (that is, serializes it). * * @serialData All of the elements (each an {@code E}) in * the proper order, followed by a null - * @param s the stream */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { @@ -1310,10 +1308,7 @@ public class LinkedTransferQueue extends AbstractQueue } /** - * Reconstitutes the Queue instance from a stream (that is, - * deserializes it). - * - * @param s the stream + * Reconstitutes this queue from a stream (that is, deserializes it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { diff --git a/src/share/classes/java/util/concurrent/RecursiveAction.java b/src/share/classes/java/util/concurrent/RecursiveAction.java index add4a54a4..6796789dd 100644 --- a/src/share/classes/java/util/concurrent/RecursiveAction.java +++ b/src/share/classes/java/util/concurrent/RecursiveAction.java @@ -39,37 +39,49 @@ package java.util.concurrent; * A recursive resultless {@link ForkJoinTask}. This class * establishes conventions to parameterize resultless actions as * {@code Void} {@code ForkJoinTask}s. Because {@code null} is the - * only valid value of type {@code Void}, methods such as join always - * return {@code null} upon completion. + * only valid value of type {@code Void}, methods such as {@code join} + * always return {@code null} upon completion. * - *

Sample Usages. Here is a sketch of a ForkJoin sort that - * sorts a given {@code long[]} array: + *

Sample Usages. Here is a simple but complete ForkJoin + * sort that sorts a given {@code long[]} array: * *

 {@code
- * class SortTask extends RecursiveAction {
- *   final long[] array; final int lo; final int hi;
+ * static class SortTask extends RecursiveAction {
+ *   final long[] array; final int lo, hi;
  *   SortTask(long[] array, int lo, int hi) {
  *     this.array = array; this.lo = lo; this.hi = hi;
  *   }
+ *   SortTask(long[] array) { this(array, 0, array.length); }
  *   protected void compute() {
  *     if (hi - lo < THRESHOLD)
- *       sequentiallySort(array, lo, hi);
+ *       sortSequentially(lo, hi);
  *     else {
  *       int mid = (lo + hi) >>> 1;
  *       invokeAll(new SortTask(array, lo, mid),
  *                 new SortTask(array, mid, hi));
- *       merge(array, lo, hi);
+ *       merge(lo, mid, hi);
  *     }
  *   }
+ *   // implementation details follow:
+ *   final static int THRESHOLD = 1000;
+ *   void sortSequentially(int lo, int hi) {
+ *     Arrays.sort(array, lo, hi);
+ *   }
+ *   void merge(int lo, int mid, int hi) {
+ *     long[] buf = Arrays.copyOfRange(array, lo, mid);
+ *     for (int i = 0, j = lo, k = mid; i < buf.length; j++)
+ *       array[j] = (k == hi || buf[i] < array[k]) ?
+ *         buf[i++] : array[k++];
+ *   }
  * }}
* * You could then sort {@code anArray} by creating {@code new - * SortTask(anArray, 0, anArray.length-1) } and invoking it in a - * ForkJoinPool. As a more concrete simple example, the following - * task increments each element of an array: + * SortTask(anArray)} and invoking it in a ForkJoinPool. As a more + * concrete simple example, the following task increments each element + * of an array: *
 {@code
  * class IncrementTask extends RecursiveAction {
- *   final long[] array; final int lo; final int hi;
+ *   final long[] array; final int lo, hi;
  *   IncrementTask(long[] array, int lo, int hi) {
  *     this.array = array; this.lo = lo; this.hi = hi;
  *   }
diff --git a/src/share/classes/java/util/concurrent/RejectedExecutionException.java b/src/share/classes/java/util/concurrent/RejectedExecutionException.java
index 9e5994539..abc8fbed3 100644
--- a/src/share/classes/java/util/concurrent/RejectedExecutionException.java
+++ b/src/share/classes/java/util/concurrent/RejectedExecutionException.java
@@ -78,8 +78,8 @@ public class RejectedExecutionException extends RuntimeException {
 
     /**
      * Constructs a RejectedExecutionException with the
-     * specified cause.  The detail message is set to: 
 (cause ==
-     * null ? null : cause.toString())
(which typically contains + * specified cause. The detail message is set to {@code (cause == + * null ? null : cause.toString())} (which typically contains * the class and detail message of cause). * * @param cause the cause (which is saved for later retrieval by the diff --git a/src/share/classes/java/util/concurrent/ScheduledExecutorService.java b/src/share/classes/java/util/concurrent/ScheduledExecutorService.java index 187d6a193..e60786a29 100644 --- a/src/share/classes/java/util/concurrent/ScheduledExecutorService.java +++ b/src/share/classes/java/util/concurrent/ScheduledExecutorService.java @@ -34,8 +34,6 @@ */ package java.util.concurrent; -import java.util.concurrent.atomic.*; -import java.util.*; /** * An {@link ExecutorService} that can schedule commands to run after a given diff --git a/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java b/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java index 49195b87c..f40859603 100644 --- a/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java +++ b/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java @@ -223,7 +223,7 @@ public class ScheduledThreadPoolExecutor } /** - * Creates a one-shot action with given nanoTime-based trigger. + * Creates a one-shot action with given nanoTime-based trigger time. */ ScheduledFutureTask(Callable callable, long ns) { super(callable); @@ -237,7 +237,7 @@ public class ScheduledThreadPoolExecutor } public int compareTo(Delayed other) { - if (other == this) // compare zero ONLY if same object + if (other == this) // compare zero if same object return 0; if (other instanceof ScheduledFutureTask) { ScheduledFutureTask x = (ScheduledFutureTask)other; @@ -251,9 +251,8 @@ public class ScheduledThreadPoolExecutor else return 1; } - long d = (getDelay(NANOSECONDS) - - other.getDelay(NANOSECONDS)); - return (d == 0) ? 0 : ((d < 0) ? -1 : 1); + long diff = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS); + return (diff < 0) ? -1 : (diff > 0) ? 1 : 0; } /** @@ -862,7 +861,7 @@ public class ScheduledThreadPoolExecutor private final Condition available = lock.newCondition(); /** - * Set f's heapIndex if it is a ScheduledFutureTask. + * Sets f's heapIndex if it is a ScheduledFutureTask. */ private void setIndex(RunnableScheduledFuture f, int idx) { if (f instanceof ScheduledFutureTask) @@ -870,7 +869,7 @@ public class ScheduledThreadPoolExecutor } /** - * Sift element added at bottom up to its heap-ordered spot. + * Sifts element added at bottom up to its heap-ordered spot. * Call only when holding lock. */ private void siftUp(int k, RunnableScheduledFuture key) { @@ -888,7 +887,7 @@ public class ScheduledThreadPoolExecutor } /** - * Sift element added at top down to its heap-ordered spot. + * Sifts element added at top down to its heap-ordered spot. * Call only when holding lock. */ private void siftDown(int k, RunnableScheduledFuture key) { @@ -910,7 +909,7 @@ public class ScheduledThreadPoolExecutor } /** - * Resize the heap array. Call only when holding lock. + * Resizes the heap array. Call only when holding lock. */ private void grow() { int oldCapacity = queue.length; @@ -921,7 +920,7 @@ public class ScheduledThreadPoolExecutor } /** - * Find index of given object, or -1 if absent + * Finds index of given object, or -1 if absent. */ private int indexOf(Object x) { if (x != null) { @@ -1162,15 +1161,14 @@ public class ScheduledThreadPoolExecutor } /** - * Return and remove first element only if it is expired. + * Returns first element only if it is expired. * Used only by drainTo. Call only when holding lock. */ - private RunnableScheduledFuture pollExpired() { + private RunnableScheduledFuture peekExpired() { // assert lock.isHeldByCurrentThread(); RunnableScheduledFuture first = queue[0]; - if (first == null || first.getDelay(NANOSECONDS) > 0) - return null; - return finishPoll(first); + return (first == null || first.getDelay(NANOSECONDS) > 0) ? + null : first; } public int drainTo(Collection c) { @@ -1183,8 +1181,9 @@ public class ScheduledThreadPoolExecutor try { RunnableScheduledFuture first; int n = 0; - while ((first = pollExpired()) != null) { - c.add(first); + while ((first = peekExpired()) != null) { + c.add(first); // In this order, in case add() throws. + finishPoll(first); ++n; } return n; @@ -1205,8 +1204,9 @@ public class ScheduledThreadPoolExecutor try { RunnableScheduledFuture first; int n = 0; - while (n < maxElements && (first = pollExpired()) != null) { - c.add(first); + while (n < maxElements && (first = peekExpired()) != null) { + c.add(first); // In this order, in case add() throws. + finishPoll(first); ++n; } return n; diff --git a/src/share/classes/java/util/concurrent/Semaphore.java b/src/share/classes/java/util/concurrent/Semaphore.java index c144b492d..4ce115178 100644 --- a/src/share/classes/java/util/concurrent/Semaphore.java +++ b/src/share/classes/java/util/concurrent/Semaphore.java @@ -34,9 +34,8 @@ */ package java.util.concurrent; -import java.util.*; -import java.util.concurrent.locks.*; -import java.util.concurrent.atomic.*; +import java.util.Collection; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; /** * A counting semaphore. Conceptually, a semaphore maintains a set of @@ -49,7 +48,7 @@ import java.util.concurrent.atomic.*; *

Semaphores are often used to restrict the number of threads than can * access some (physical or logical) resource. For example, here is * a class that uses a semaphore to control access to a pool of items: - *

+ *  
 {@code
  * class Pool {
  *   private static final int MAX_AVAILABLE = 100;
  *   private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
@@ -91,9 +90,7 @@ import java.util.concurrent.atomic.*;
  *     }
  *     return false;
  *   }
- *
- * }
- * 
+ * }}
* *

Before obtaining an item each thread must acquire a permit from * the semaphore, guaranteeing that an item is available for use. When @@ -111,7 +108,7 @@ import java.util.concurrent.atomic.*; * exclusion lock. This is more commonly known as a binary * semaphore, because it only has two states: one permit * available, or zero permits available. When used in this way, the - * binary semaphore has the property (unlike many {@link Lock} + * binary semaphore has the property (unlike many {@link java.util.concurrent.locks.Lock} * implementations), that the "lock" can be released by a * thread other than the owner (as semaphores have no notion of * ownership). This can be useful in some specialized contexts, such @@ -155,9 +152,7 @@ import java.util.concurrent.atomic.*; * * @since 1.5 * @author Doug Lea - * */ - public class Semaphore implements java.io.Serializable { private static final long serialVersionUID = -3222578661600680210L; /** All mechanics via AbstractQueuedSynchronizer subclass */ @@ -493,7 +488,6 @@ public class Semaphore implements java.io.Serializable { * * @param permits the number of permits to acquire * @throws IllegalArgumentException if {@code permits} is negative - * */ public void acquireUninterruptibly(int permits) { if (permits < 0) throw new IllegalArgumentException(); diff --git a/src/share/classes/java/util/concurrent/SynchronousQueue.java b/src/share/classes/java/util/concurrent/SynchronousQueue.java index 9d0d830c2..ee9b12188 100644 --- a/src/share/classes/java/util/concurrent/SynchronousQueue.java +++ b/src/share/classes/java/util/concurrent/SynchronousQueue.java @@ -35,7 +35,8 @@ */ package java.util.concurrent; -import java.util.concurrent.locks.*; +import java.util.concurrent.locks.LockSupport; +import java.util.concurrent.locks.ReentrantLock; import java.util.*; /** @@ -222,7 +223,7 @@ public class SynchronousQueue extends AbstractQueue /** Node is fulfilling another unfulfilled DATA or REQUEST */ static final int FULFILLING = 2; - /** Return true if m has fulfilling bit set */ + /** Returns true if m has fulfilling bit set. */ static boolean isFulfilling(int m) { return (m & FULFILLING) != 0; } /** Node class for TransferStacks. */ @@ -430,9 +431,8 @@ public class SynchronousQueue extends AbstractQueue * and don't wait at all, so are trapped in transfer * method rather than calling awaitFulfill. */ - long lastTime = timed ? System.nanoTime() : 0; + final long deadline = timed ? System.nanoTime() + nanos : 0L; Thread w = Thread.currentThread(); - SNode h = head; int spins = (shouldSpin(s) ? (timed ? maxTimedSpins : maxUntimedSpins) : 0); for (;;) { @@ -442,10 +442,8 @@ public class SynchronousQueue extends AbstractQueue if (m != null) return m; if (timed) { - long now = System.nanoTime(); - nanos -= now - lastTime; - lastTime = now; - if (nanos <= 0) { + nanos = deadline - System.nanoTime(); + if (nanos <= 0L) { s.tryCancel(); continue; } @@ -737,7 +735,7 @@ public class SynchronousQueue extends AbstractQueue */ Object awaitFulfill(QNode s, E e, boolean timed, long nanos) { /* Same idea as TransferStack.awaitFulfill */ - long lastTime = timed ? System.nanoTime() : 0; + final long deadline = timed ? System.nanoTime() + nanos : 0L; Thread w = Thread.currentThread(); int spins = ((head.next == s) ? (timed ? maxTimedSpins : maxUntimedSpins) : 0); @@ -748,10 +746,8 @@ public class SynchronousQueue extends AbstractQueue if (x != e) return x; if (timed) { - long now = System.nanoTime(); - nanos -= now - lastTime; - lastTime = now; - if (nanos <= 0) { + nanos = deadline - System.nanoTime(); + if (nanos <= 0L) { s.tryCancel(e); continue; } @@ -874,9 +870,9 @@ public class SynchronousQueue extends AbstractQueue * @throws InterruptedException {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ - public void put(E o) throws InterruptedException { - if (o == null) throw new NullPointerException(); - if (transferer.transfer(o, false, 0) == null) { + public void put(E e) throws InterruptedException { + if (e == null) throw new NullPointerException(); + if (transferer.transfer(e, false, 0) == null) { Thread.interrupted(); throw new InterruptedException(); } @@ -891,10 +887,10 @@ public class SynchronousQueue extends AbstractQueue * @throws InterruptedException {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ - public boolean offer(E o, long timeout, TimeUnit unit) + public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException { - if (o == null) throw new NullPointerException(); - if (transferer.transfer(o, true, unit.toNanos(timeout)) != null) + if (e == null) throw new NullPointerException(); + if (transferer.transfer(e, true, unit.toNanos(timeout)) != null) return true; if (!Thread.interrupted()) return false; @@ -1162,9 +1158,7 @@ public class SynchronousQueue extends AbstractQueue private WaitQueue waitingConsumers; /** - * Saves the state to a stream (that is, serializes it). - * - * @param s the stream + * Saves this queue to a stream (that is, serializes it). */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { @@ -1182,6 +1176,9 @@ public class SynchronousQueue extends AbstractQueue s.defaultWriteObject(); } + /** + * Reconstitutes this queue from a stream (that is, deserializes it). + */ private void readObject(final java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); diff --git a/src/share/classes/java/util/concurrent/ThreadFactory.java b/src/share/classes/java/util/concurrent/ThreadFactory.java index 9274abc5f..a0e21e211 100644 --- a/src/share/classes/java/util/concurrent/ThreadFactory.java +++ b/src/share/classes/java/util/concurrent/ThreadFactory.java @@ -42,13 +42,12 @@ package java.util.concurrent; * *

* The simplest implementation of this interface is just: - *

+ *  
 {@code
  * class SimpleThreadFactory implements ThreadFactory {
  *   public Thread newThread(Runnable r) {
  *     return new Thread(r);
  *   }
- * }
- * 
+ * }}
* * The {@link Executors#defaultThreadFactory} method provides a more * useful simple implementation, that sets the created thread context diff --git a/src/share/classes/java/util/concurrent/TimeUnit.java b/src/share/classes/java/util/concurrent/TimeUnit.java index f756759e8..ab3aa854f 100644 --- a/src/share/classes/java/util/concurrent/TimeUnit.java +++ b/src/share/classes/java/util/concurrent/TimeUnit.java @@ -52,14 +52,14 @@ package java.util.concurrent; * the following code will timeout in 50 milliseconds if the {@link * java.util.concurrent.locks.Lock lock} is not available: * - *
  Lock lock = ...;
- *  if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...
- * 
+ *
 {@code
+ * Lock lock = ...;
+ * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...}
+ * * while this code will timeout in 50 seconds: - *
- *  Lock lock = ...;
- *  if (lock.tryLock(50L, TimeUnit.SECONDS)) ...
- * 
+ *
 {@code
+ * Lock lock = ...;
+ * if (lock.tryLock(50L, TimeUnit.SECONDS)) ...}
* * Note however, that there is no guarantee that a particular timeout * implementation will be able to notice the passage of time at the diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java b/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java index 1bc7fa2aa..0d509cda0 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java @@ -245,7 +245,6 @@ public class AtomicInteger extends Number implements java.io.Serializable { return Integer.toString(get()); } - /** * Returns the value of this {@code AtomicInteger} as an {@code int}. */ diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java index dc26f4c0b..a692479ad 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java @@ -59,7 +59,7 @@ import java.security.PrivilegedActionException; * @author Doug Lea * @param The type of the object holding the updatable field */ -public abstract class AtomicIntegerFieldUpdater { +public abstract class AtomicIntegerFieldUpdater { /** * Creates and returns an updater for objects with the given field. * The Class argument is needed to check that reflective types and @@ -274,9 +274,9 @@ public abstract class AtomicIntegerFieldUpdater { private final Class cclass; AtomicIntegerFieldUpdaterImpl(final Class tclass, final String fieldName) { - Field field = null; - Class caller = null; - int modifiers = 0; + final Field field; + final Class caller; + final int modifiers; try { field = AccessController.doPrivileged( new PrivilegedExceptionAction() { diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicLong.java b/src/share/classes/java/util/concurrent/atomic/AtomicLong.java index f503d577d..7813aad04 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicLong.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicLong.java @@ -259,7 +259,6 @@ public class AtomicLong extends Number implements java.io.Serializable { return Long.toString(get()); } - /** * Returns the value of this {@code AtomicLong} as an {@code int} * after a narrowing primitive conversion. diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java index 3311aecdb..8b80684d8 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java @@ -59,7 +59,7 @@ import java.security.PrivilegedActionException; * @author Doug Lea * @param The type of the object holding the updatable field */ -public abstract class AtomicLongFieldUpdater { +public abstract class AtomicLongFieldUpdater { /** * Creates and returns an updater for objects with the given field. * The Class argument is needed to check that reflective types and @@ -274,9 +274,9 @@ public abstract class AtomicLongFieldUpdater { private final Class cclass; CASUpdater(final Class tclass, final String fieldName) { - Field field = null; - Class caller = null; - int modifiers = 0; + final Field field; + final Class caller; + final int modifiers; try { field = AccessController.doPrivileged( new PrivilegedExceptionAction() { diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicReference.java b/src/share/classes/java/util/concurrent/atomic/AtomicReference.java index 978664e2d..8bbc25c69 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicReference.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicReference.java @@ -44,7 +44,7 @@ import sun.misc.Unsafe; * @author Doug Lea * @param The type of object referred to by this reference */ -public class AtomicReference implements java.io.Serializable { +public class AtomicReference implements java.io.Serializable { private static final long serialVersionUID = -1848883965231344442L; private static final Unsafe unsafe = Unsafe.getUnsafe(); diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java index 8459e7c4f..015523ff3 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -35,8 +35,8 @@ package java.util.concurrent.atomic; -import java.lang.reflect.Array; import java.util.Arrays; +import java.lang.reflect.Array; import sun.misc.Unsafe; /** @@ -151,7 +151,6 @@ public class AtomicReferenceArray implements java.io.Serializable { unsafe.putOrderedObject(array, checkedByteOffset(i), newValue); } - /** * Atomically sets the element at position {@code i} to the given * value and returns the old value. @@ -225,10 +224,10 @@ public class AtomicReferenceArray implements java.io.Serializable { /** * Reconstitutes the instance from a stream (that is, deserializes it). - * @param s the stream */ private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { + throws java.io.IOException, ClassNotFoundException, + java.io.InvalidObjectException { // Note: This must be changed if any additional fields are defined Object a = s.readFields().get("array", null); if (a == null || !a.getClass().isArray()) diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java index bba703e67..2bb1fae40 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java @@ -206,10 +206,10 @@ public abstract class AtomicReferenceFieldUpdater { AtomicReferenceFieldUpdaterImpl(final Class tclass, Class vclass, final String fieldName) { - Field field = null; - Class fieldClass = null; - Class caller = null; - int modifiers = 0; + final Field field; + final Class fieldClass; + final Class caller; + final int modifiers; try { field = AccessController.doPrivileged( new PrivilegedExceptionAction() { @@ -220,12 +220,12 @@ public abstract class AtomicReferenceFieldUpdater { caller = sun.reflect.Reflection.getCallerClass(3); modifiers = field.getModifiers(); sun.reflect.misc.ReflectUtil.ensureMemberAccess( - caller, tclass, null, modifiers); + caller, tclass, null, modifiers); ClassLoader cl = tclass.getClassLoader(); ClassLoader ccl = caller.getClassLoader(); if ((ccl != null) && (ccl != cl) && ((cl == null) || !isAncestor(cl, ccl))) { - sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); + sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); } fieldClass = field.getType(); } catch (PrivilegedActionException pae) { @@ -315,7 +315,7 @@ public abstract class AtomicReferenceFieldUpdater { } @SuppressWarnings("unchecked") - public V get(T obj) { + public V get(T obj) { if (obj == null || obj.getClass() != tclass || cclass != null) targetCheck(obj); return (V)unsafe.getObjectVolatile(obj, offset); @@ -326,14 +326,14 @@ public abstract class AtomicReferenceFieldUpdater { return; } throw new RuntimeException( - new IllegalAccessException("Class " + - cclass.getName() + - " can not access a protected member of class " + - tclass.getName() + - " using an instance of " + - obj.getClass().getName() - ) - ); + new IllegalAccessException("Class " + + cclass.getName() + + " can not access a protected member of class " + + tclass.getName() + + " using an instance of " + + obj.getClass().getName() + ) + ); } } } diff --git a/src/share/classes/java/util/concurrent/atomic/package-info.java b/src/share/classes/java/util/concurrent/atomic/package-info.java index 7c0ba5e86..5cc259562 100644 --- a/src/share/classes/java/util/concurrent/atomic/package-info.java +++ b/src/share/classes/java/util/concurrent/atomic/package-info.java @@ -40,9 +40,7 @@ * array elements to those that also provide an atomic conditional update * operation of the form: * - *
- *   boolean compareAndSet(expectedValue, updateValue);
- * 
+ *
 {@code boolean compareAndSet(expectedValue, updateValue);}
* *

This method (which varies in argument types across different * classes) atomically sets a variable to the {@code updateValue} if it @@ -69,19 +67,36 @@ * {@code AtomicInteger} provide atomic increment methods. One * application is to generate sequence numbers, as in: * - *

+ *  
 {@code
  * class Sequencer {
  *   private final AtomicLong sequenceNumber
  *     = new AtomicLong(0);
  *   public long next() {
  *     return sequenceNumber.getAndIncrement();
  *   }
- * }
- * 
+ * }}
+ * + *

It is straightforward to define new utility functions that, like + * {@code getAndIncrement}, apply a function to a value atomically. + * For example, given some transformation + *

 {@code long transform(long input)}
+ * + * write your utility method as follows: + *
 {@code
+ * long getAndTransform(AtomicLong var) {
+ *   while (true) {
+ *     long current = var.get();
+ *     long next = transform(current);
+ *     if (var.compareAndSet(current, next))
+ *         return current;
+ *         // return next; for transformAndGet
+ *   }
+ * }}
* *

The memory effects for accesses and updates of atomics generally - * follow the rules for volatiles, as stated in section 17.4 of - * The Java™ Language Specification. + * follow the rules for volatiles, as stated in + * + * The Java Language Specification, Third Edition (17.4 Memory Model): * *

    * @@ -189,9 +204,9 @@ * {@code byte} values, and cast appropriately. * * You can also hold floats using - * {@link java.lang.Float#floatToIntBits} and + * {@link java.lang.Float#floatToRawIntBits} and * {@link java.lang.Float#intBitsToFloat} conversions, and doubles using - * {@link java.lang.Double#doubleToLongBits} and + * {@link java.lang.Double#doubleToRawLongBits} and * {@link java.lang.Double#longBitsToDouble} conversions. * * @since 1.5 diff --git a/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java index 15490bd36..46ad577cf 100644 --- a/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java +++ b/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java @@ -34,9 +34,10 @@ */ package java.util.concurrent.locks; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; +import java.util.concurrent.TimeUnit; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; import sun.misc.Unsafe; /** @@ -598,7 +599,7 @@ public abstract class AbstractQueuedLongSynchronizer /** * Convenience method to interrupt current thread. */ - private static void selfInterrupt() { + static void selfInterrupt() { Thread.currentThread().interrupt(); } @@ -686,8 +687,10 @@ public abstract class AbstractQueuedLongSynchronizer * @return {@code true} if acquired */ private boolean doAcquireNanos(long arg, long nanosTimeout) - throws InterruptedException { - long lastTime = System.nanoTime(); + throws InterruptedException { + if (nanosTimeout <= 0L) + return false; + final long deadline = System.nanoTime() + nanosTimeout; final Node node = addWaiter(Node.EXCLUSIVE); boolean failed = true; try { @@ -699,14 +702,12 @@ public abstract class AbstractQueuedLongSynchronizer failed = false; return true; } - if (nanosTimeout <= 0) + nanosTimeout = deadline - System.nanoTime(); + if (nanosTimeout <= 0L) return false; if (shouldParkAfterFailedAcquire(p, node) && nanosTimeout > spinForTimeoutThreshold) LockSupport.parkNanos(this, nanosTimeout); - long now = System.nanoTime(); - nanosTimeout -= now - lastTime; - lastTime = now; if (Thread.interrupted()) throw new InterruptedException(); } @@ -786,9 +787,10 @@ public abstract class AbstractQueuedLongSynchronizer * @return {@code true} if acquired */ private boolean doAcquireSharedNanos(long arg, long nanosTimeout) - throws InterruptedException { - - long lastTime = System.nanoTime(); + throws InterruptedException { + if (nanosTimeout <= 0L) + return false; + final long deadline = System.nanoTime() + nanosTimeout; final Node node = addWaiter(Node.SHARED); boolean failed = true; try { @@ -803,14 +805,12 @@ public abstract class AbstractQueuedLongSynchronizer return true; } } - if (nanosTimeout <= 0) + nanosTimeout = deadline - System.nanoTime(); + if (nanosTimeout <= 0L) return false; if (shouldParkAfterFailedAcquire(p, node) && nanosTimeout > spinForTimeoutThreshold) LockSupport.parkNanos(this, nanosTimeout); - long now = System.nanoTime(); - nanosTimeout -= now - lastTime; - lastTime = now; if (Thread.interrupted()) throw new InterruptedException(); } @@ -1260,7 +1260,7 @@ public abstract class AbstractQueuedLongSynchronizer * due to the queue being empty. * *

    This method is designed to be used by a fair synchronizer to - * avoid barging. + * avoid barging. * Such a synchronizer's {@link #tryAcquire} method should return * {@code false}, and its {@link #tryAcquireShared} method should * return a negative value, if this method returns {@code true} @@ -1520,8 +1520,6 @@ public abstract class AbstractQueuedLongSynchronizer * @throws NullPointerException if the condition is null */ public final boolean owns(ConditionObject condition) { - if (condition == null) - throw new NullPointerException(); return condition.isOwnedBy(this); } @@ -1742,9 +1740,8 @@ public abstract class AbstractQueuedLongSynchronizer * Implements uninterruptible condition wait. *

      *
    1. Save lock state returned by {@link #getState}. - *
    2. Invoke {@link #release} with - * saved state as argument, throwing - * IllegalMonitorStateException if it fails. + *
    3. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. *
    4. Block until signalled. *
    5. Reacquire by invoking specialized version of * {@link #acquire} with saved state as argument. @@ -1803,9 +1800,8 @@ public abstract class AbstractQueuedLongSynchronizer *
        *
      1. If current thread is interrupted, throw InterruptedException. *
      2. Save lock state returned by {@link #getState}. - *
      3. Invoke {@link #release} with - * saved state as argument, throwing - * IllegalMonitorStateException if it fails. + *
      4. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. *
      5. Block until signalled or interrupted. *
      6. Reacquire by invoking specialized version of * {@link #acquire} with saved state as argument. @@ -1836,9 +1832,8 @@ public abstract class AbstractQueuedLongSynchronizer *
          *
        1. If current thread is interrupted, throw InterruptedException. *
        2. Save lock state returned by {@link #getState}. - *
        3. Invoke {@link #release} with - * saved state as argument, throwing - * IllegalMonitorStateException if it fails. + *
        4. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. *
        5. Block until signalled, interrupted, or timed out. *
        6. Reacquire by invoking specialized version of * {@link #acquire} with saved state as argument. @@ -1851,20 +1846,18 @@ public abstract class AbstractQueuedLongSynchronizer throw new InterruptedException(); Node node = addConditionWaiter(); long savedState = fullyRelease(node); - long lastTime = System.nanoTime(); + final long deadline = System.nanoTime() + nanosTimeout; int interruptMode = 0; while (!isOnSyncQueue(node)) { if (nanosTimeout <= 0L) { transferAfterCancelledWait(node); break; } - LockSupport.parkNanos(this, nanosTimeout); + if (nanosTimeout >= spinForTimeoutThreshold) + LockSupport.parkNanos(this, nanosTimeout); if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) break; - - long now = System.nanoTime(); - nanosTimeout -= now - lastTime; - lastTime = now; + nanosTimeout = deadline - System.nanoTime(); } if (acquireQueued(node, savedState) && interruptMode != THROW_IE) interruptMode = REINTERRUPT; @@ -1872,7 +1865,7 @@ public abstract class AbstractQueuedLongSynchronizer unlinkCancelledWaiters(); if (interruptMode != 0) reportInterruptAfterWait(interruptMode); - return nanosTimeout - (System.nanoTime() - lastTime); + return deadline - System.nanoTime(); } /** @@ -1880,9 +1873,8 @@ public abstract class AbstractQueuedLongSynchronizer *
            *
          1. If current thread is interrupted, throw InterruptedException. *
          2. Save lock state returned by {@link #getState}. - *
          3. Invoke {@link #release} with - * saved state as argument, throwing - * IllegalMonitorStateException if it fails. + *
          4. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. *
          5. Block until signalled, interrupted, or timed out. *
          6. Reacquire by invoking specialized version of * {@link #acquire} with saved state as argument. @@ -1892,8 +1884,6 @@ public abstract class AbstractQueuedLongSynchronizer */ public final boolean awaitUntil(Date deadline) throws InterruptedException { - if (deadline == null) - throw new NullPointerException(); long abstime = deadline.getTime(); if (Thread.interrupted()) throw new InterruptedException(); @@ -1924,9 +1914,8 @@ public abstract class AbstractQueuedLongSynchronizer *
              *
            1. If current thread is interrupted, throw InterruptedException. *
            2. Save lock state returned by {@link #getState}. - *
            3. Invoke {@link #release} with - * saved state as argument, throwing - * IllegalMonitorStateException if it fails. + *
            4. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. *
            5. Block until signalled, interrupted, or timed out. *
            6. Reacquire by invoking specialized version of * {@link #acquire} with saved state as argument. @@ -1936,14 +1925,12 @@ public abstract class AbstractQueuedLongSynchronizer */ public final boolean await(long time, TimeUnit unit) throws InterruptedException { - if (unit == null) - throw new NullPointerException(); long nanosTimeout = unit.toNanos(time); if (Thread.interrupted()) throw new InterruptedException(); Node node = addConditionWaiter(); long savedState = fullyRelease(node); - long lastTime = System.nanoTime(); + final long deadline = System.nanoTime() + nanosTimeout; boolean timedout = false; int interruptMode = 0; while (!isOnSyncQueue(node)) { @@ -1955,9 +1942,7 @@ public abstract class AbstractQueuedLongSynchronizer LockSupport.parkNanos(this, nanosTimeout); if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) break; - long now = System.nanoTime(); - nanosTimeout -= now - lastTime; - lastTime = now; + nanosTimeout = deadline - System.nanoTime(); } if (acquireQueued(node, savedState) && interruptMode != THROW_IE) interruptMode = REINTERRUPT; diff --git a/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java index 0da0eaeca..6f39256c0 100644 --- a/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java +++ b/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java @@ -34,9 +34,10 @@ */ package java.util.concurrent.locks; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; +import java.util.concurrent.TimeUnit; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; import sun.misc.Unsafe; /** @@ -194,7 +195,7 @@ import sun.misc.Unsafe; * It also supports conditions and exposes * one of the instrumentation methods: * - *
              + *  
               {@code
                * class Mutex implements Lock, java.io.Serializable {
                *
                *   // Our internal helper class
              @@ -250,15 +251,15 @@ import sun.misc.Unsafe;
                *       throws InterruptedException {
                *     return sync.tryAcquireNanos(1, unit.toNanos(timeout));
                *   }
              - * }
              - * 
              + * }}
              * - *

              Here is a latch class that is like a {@link CountDownLatch} + *

              Here is a latch class that is like a + * {@link java.util.concurrent.CountDownLatch CountDownLatch} * except that it only requires a single signal to * fire. Because a latch is non-exclusive, it uses the shared * acquire and release methods. * - *

              + *  
               {@code
                * class BooleanLatch {
                *
                *   private static class Sync extends AbstractQueuedSynchronizer {
              @@ -280,8 +281,7 @@ import sun.misc.Unsafe;
                *   public void await() throws InterruptedException {
                *     sync.acquireSharedInterruptibly(1);
                *   }
              - * }
              - * 
              + * }}
              * * @since 1.5 * @author Doug Lea @@ -821,7 +821,7 @@ public abstract class AbstractQueuedSynchronizer /** * Convenience method to interrupt current thread. */ - private static void selfInterrupt() { + static void selfInterrupt() { Thread.currentThread().interrupt(); } @@ -909,8 +909,10 @@ public abstract class AbstractQueuedSynchronizer * @return {@code true} if acquired */ private boolean doAcquireNanos(int arg, long nanosTimeout) - throws InterruptedException { - long lastTime = System.nanoTime(); + throws InterruptedException { + if (nanosTimeout <= 0L) + return false; + final long deadline = System.nanoTime() + nanosTimeout; final Node node = addWaiter(Node.EXCLUSIVE); boolean failed = true; try { @@ -922,14 +924,12 @@ public abstract class AbstractQueuedSynchronizer failed = false; return true; } - if (nanosTimeout <= 0) + nanosTimeout = deadline - System.nanoTime(); + if (nanosTimeout <= 0L) return false; if (shouldParkAfterFailedAcquire(p, node) && nanosTimeout > spinForTimeoutThreshold) LockSupport.parkNanos(this, nanosTimeout); - long now = System.nanoTime(); - nanosTimeout -= now - lastTime; - lastTime = now; if (Thread.interrupted()) throw new InterruptedException(); } @@ -1009,9 +1009,10 @@ public abstract class AbstractQueuedSynchronizer * @return {@code true} if acquired */ private boolean doAcquireSharedNanos(int arg, long nanosTimeout) - throws InterruptedException { - - long lastTime = System.nanoTime(); + throws InterruptedException { + if (nanosTimeout <= 0L) + return false; + final long deadline = System.nanoTime() + nanosTimeout; final Node node = addWaiter(Node.SHARED); boolean failed = true; try { @@ -1026,14 +1027,12 @@ public abstract class AbstractQueuedSynchronizer return true; } } - if (nanosTimeout <= 0) + nanosTimeout = deadline - System.nanoTime(); + if (nanosTimeout <= 0L) return false; if (shouldParkAfterFailedAcquire(p, node) && nanosTimeout > spinForTimeoutThreshold) LockSupport.parkNanos(this, nanosTimeout); - long now = System.nanoTime(); - nanosTimeout -= now - lastTime; - lastTime = now; if (Thread.interrupted()) throw new InterruptedException(); } @@ -1743,8 +1742,6 @@ public abstract class AbstractQueuedSynchronizer * @throws NullPointerException if the condition is null */ public final boolean owns(ConditionObject condition) { - if (condition == null) - throw new NullPointerException(); return condition.isOwnedBy(this); } @@ -1963,9 +1960,8 @@ public abstract class AbstractQueuedSynchronizer * Implements uninterruptible condition wait. *
                *
              1. Save lock state returned by {@link #getState}. - *
              2. Invoke {@link #release} with - * saved state as argument, throwing - * IllegalMonitorStateException if it fails. + *
              3. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. *
              4. Block until signalled. *
              5. Reacquire by invoking specialized version of * {@link #acquire} with saved state as argument. @@ -2024,9 +2020,8 @@ public abstract class AbstractQueuedSynchronizer *
                  *
                1. If current thread is interrupted, throw InterruptedException. *
                2. Save lock state returned by {@link #getState}. - *
                3. Invoke {@link #release} with - * saved state as argument, throwing - * IllegalMonitorStateException if it fails. + *
                4. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. *
                5. Block until signalled or interrupted. *
                6. Reacquire by invoking specialized version of * {@link #acquire} with saved state as argument. @@ -2057,9 +2052,8 @@ public abstract class AbstractQueuedSynchronizer *
                    *
                  1. If current thread is interrupted, throw InterruptedException. *
                  2. Save lock state returned by {@link #getState}. - *
                  3. Invoke {@link #release} with - * saved state as argument, throwing - * IllegalMonitorStateException if it fails. + *
                  4. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. *
                  5. Block until signalled, interrupted, or timed out. *
                  6. Reacquire by invoking specialized version of * {@link #acquire} with saved state as argument. @@ -2072,20 +2066,18 @@ public abstract class AbstractQueuedSynchronizer throw new InterruptedException(); Node node = addConditionWaiter(); int savedState = fullyRelease(node); - long lastTime = System.nanoTime(); + final long deadline = System.nanoTime() + nanosTimeout; int interruptMode = 0; while (!isOnSyncQueue(node)) { if (nanosTimeout <= 0L) { transferAfterCancelledWait(node); break; } - LockSupport.parkNanos(this, nanosTimeout); + if (nanosTimeout >= spinForTimeoutThreshold) + LockSupport.parkNanos(this, nanosTimeout); if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) break; - - long now = System.nanoTime(); - nanosTimeout -= now - lastTime; - lastTime = now; + nanosTimeout = deadline - System.nanoTime(); } if (acquireQueued(node, savedState) && interruptMode != THROW_IE) interruptMode = REINTERRUPT; @@ -2093,7 +2085,7 @@ public abstract class AbstractQueuedSynchronizer unlinkCancelledWaiters(); if (interruptMode != 0) reportInterruptAfterWait(interruptMode); - return nanosTimeout - (System.nanoTime() - lastTime); + return deadline - System.nanoTime(); } /** @@ -2101,9 +2093,8 @@ public abstract class AbstractQueuedSynchronizer *
                      *
                    1. If current thread is interrupted, throw InterruptedException. *
                    2. Save lock state returned by {@link #getState}. - *
                    3. Invoke {@link #release} with - * saved state as argument, throwing - * IllegalMonitorStateException if it fails. + *
                    4. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. *
                    5. Block until signalled, interrupted, or timed out. *
                    6. Reacquire by invoking specialized version of * {@link #acquire} with saved state as argument. @@ -2113,8 +2104,6 @@ public abstract class AbstractQueuedSynchronizer */ public final boolean awaitUntil(Date deadline) throws InterruptedException { - if (deadline == null) - throw new NullPointerException(); long abstime = deadline.getTime(); if (Thread.interrupted()) throw new InterruptedException(); @@ -2145,9 +2134,8 @@ public abstract class AbstractQueuedSynchronizer *
                        *
                      1. If current thread is interrupted, throw InterruptedException. *
                      2. Save lock state returned by {@link #getState}. - *
                      3. Invoke {@link #release} with - * saved state as argument, throwing - * IllegalMonitorStateException if it fails. + *
                      4. Invoke {@link #release} with saved state as argument, + * throwing IllegalMonitorStateException if it fails. *
                      5. Block until signalled, interrupted, or timed out. *
                      6. Reacquire by invoking specialized version of * {@link #acquire} with saved state as argument. @@ -2157,14 +2145,12 @@ public abstract class AbstractQueuedSynchronizer */ public final boolean await(long time, TimeUnit unit) throws InterruptedException { - if (unit == null) - throw new NullPointerException(); long nanosTimeout = unit.toNanos(time); if (Thread.interrupted()) throw new InterruptedException(); Node node = addConditionWaiter(); int savedState = fullyRelease(node); - long lastTime = System.nanoTime(); + final long deadline = System.nanoTime() + nanosTimeout; boolean timedout = false; int interruptMode = 0; while (!isOnSyncQueue(node)) { @@ -2176,9 +2162,7 @@ public abstract class AbstractQueuedSynchronizer LockSupport.parkNanos(this, nanosTimeout); if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) break; - long now = System.nanoTime(); - nanosTimeout -= now - lastTime; - lastTime = now; + nanosTimeout = deadline - System.nanoTime(); } if (acquireQueued(node, savedState) && interruptMode != THROW_IE) interruptMode = REINTERRUPT; diff --git a/src/share/classes/java/util/concurrent/locks/Condition.java b/src/share/classes/java/util/concurrent/locks/Condition.java index 8bdbedea3..02cbee904 100644 --- a/src/share/classes/java/util/concurrent/locks/Condition.java +++ b/src/share/classes/java/util/concurrent/locks/Condition.java @@ -34,7 +34,7 @@ */ package java.util.concurrent.locks; -import java.util.concurrent.*; +import java.util.concurrent.TimeUnit; import java.util.Date; /** @@ -360,10 +360,9 @@ public interface Condition { /** * Causes the current thread to wait until it is signalled or interrupted, * or the specified waiting time elapses. This method is behaviorally - * equivalent to:
                        - *
                        -     *   awaitNanos(unit.toNanos(time)) > 0
                        -     * 
                        + * equivalent to: + *
                         {@code awaitNanos(unit.toNanos(time)) > 0}
                        + * * @param time the maximum time to wait * @param unit the time unit of the {@code time} argument * @return {@code false} if the waiting time detectably elapsed diff --git a/src/share/classes/java/util/concurrent/locks/Lock.java b/src/share/classes/java/util/concurrent/locks/Lock.java index 8ed346c29..d9ae1bcc4 100644 --- a/src/share/classes/java/util/concurrent/locks/Lock.java +++ b/src/share/classes/java/util/concurrent/locks/Lock.java @@ -77,14 +77,14 @@ import java.util.concurrent.TimeUnit; * methods and statements. In most cases, the following idiom * should be used: * - *
                             Lock l = ...;
                        - *     l.lock();
                        - *     try {
                        - *         // access the resource protected by this lock
                        - *     } finally {
                        - *         l.unlock();
                        - *     }
                        - * 
                        + *
                         {@code
                        + * Lock l = ...;
                        + * l.lock();
                        + * try {
                        + *   // access the resource protected by this lock
                        + * } finally {
                        + *   l.unlock();
                        + * }}
                        * * When locking and unlocking occur in different scopes, care must be * taken to ensure that all code that is executed while the lock is @@ -120,8 +120,9 @@ import java.util.concurrent.TimeUnit; * *

                        All {@code Lock} implementations must enforce the same * memory synchronization semantics as provided by the built-in monitor - * lock, as described in section 17.4 of - * The Java™ Language Specification: + * lock, as described in + * + * The Java Language Specification, Third Edition (17.4 Memory Model): *

                          *
                        • A successful {@code lock} operation has the same memory * synchronization effects as a successful Lock action. @@ -239,18 +240,18 @@ public interface Lock { * immediately with the value {@code false}. * *

                          A typical usage idiom for this method would be: - *

                          -     *      Lock lock = ...;
                          -     *      if (lock.tryLock()) {
                          -     *          try {
                          -     *              // manipulate protected state
                          -     *          } finally {
                          -     *              lock.unlock();
                          -     *          }
                          -     *      } else {
                          -     *          // perform alternative actions
                          -     *      }
                          -     * 
                          + *
                           {@code
                          +     * Lock lock = ...;
                          +     * if (lock.tryLock()) {
                          +     *   try {
                          +     *     // manipulate protected state
                          +     *   } finally {
                          +     *     lock.unlock();
                          +     *   }
                          +     * } else {
                          +     *   // perform alternative actions
                          +     * }}
                          + * * This usage ensures that the lock is unlocked if it was acquired, and * doesn't try to unlock if the lock was not acquired. * diff --git a/src/share/classes/java/util/concurrent/locks/LockSupport.java b/src/share/classes/java/util/concurrent/locks/LockSupport.java index 7b829f63a..08bd8878a 100644 --- a/src/share/classes/java/util/concurrent/locks/LockSupport.java +++ b/src/share/classes/java/util/concurrent/locks/LockSupport.java @@ -34,10 +34,8 @@ */ package java.util.concurrent.locks; -import java.util.concurrent.*; import sun.misc.Unsafe; - /** * Basic thread blocking primitives for creating locks and other * synchronization classes. @@ -78,7 +76,10 @@ import sun.misc.Unsafe; * higher-level synchronization utilities, and are not in themselves * useful for most concurrency control applications. The {@code park} * method is designed for use only in constructions of the form: - *
                          while (!canProceed()) { ... LockSupport.park(this); }
                          + * + *
                           {@code
                          + * while (!canProceed()) { ... LockSupport.park(this); }}
                          + * * where neither {@code canProceed} nor any other actions prior to the * call to {@code park} entail locking or blocking. Because only one * permit is associated with each thread, any intermediary uses of @@ -86,7 +87,7 @@ import sun.misc.Unsafe; * *

                          Sample Usage. Here is a sketch of a first-in-first-out * non-reentrant lock class: - *

                          {@code
                          + *  
                           {@code
                            * class FIFOMutex {
                            *   private final AtomicBoolean locked = new AtomicBoolean(false);
                            *   private final Queue waiters
                          @@ -116,7 +117,6 @@ import sun.misc.Unsafe;
                            *   }
                            * }}
                          */ - public class LockSupport { private LockSupport() {} // Cannot be instantiated. diff --git a/src/share/classes/java/util/concurrent/locks/ReentrantLock.java b/src/share/classes/java/util/concurrent/locks/ReentrantLock.java index 9952c8c93..5ca1335aa 100644 --- a/src/share/classes/java/util/concurrent/locks/ReentrantLock.java +++ b/src/share/classes/java/util/concurrent/locks/ReentrantLock.java @@ -34,9 +34,8 @@ */ package java.util.concurrent.locks; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; +import java.util.concurrent.TimeUnit; +import java.util.Collection; /** * A reentrant mutual exclusion {@link Lock} with the same basic @@ -73,7 +72,7 @@ import java.util.concurrent.atomic.*; * follow a call to {@code lock} with a {@code try} block, most * typically in a before/after construction such as: * - *
                          + *  
                           {@code
                            * class X {
                            *   private final ReentrantLock lock = new ReentrantLock();
                            *   // ...
                          @@ -86,8 +85,7 @@ import java.util.concurrent.atomic.*;
                            *       lock.unlock()
                            *     }
                            *   }
                          - * }
                          - * 
                          + * }}
                          * *

                          In addition to implementing the {@link Lock} interface, this * class defines methods {@code isLocked} and @@ -187,8 +185,7 @@ public class ReentrantLock implements Lock, java.io.Serializable { } /** - * Reconstitutes this lock instance from a stream. - * @param s the stream + * Reconstitutes the instance from a stream (that is, deserializes it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { @@ -383,8 +380,11 @@ public class ReentrantLock implements Lock, java.io.Serializable { * method. If you want a timed {@code tryLock} that does permit barging on * a fair lock then combine the timed and un-timed forms together: * - *

                          if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
                          -     * 
                          + *
                           {@code
                          +     * if (lock.tryLock() ||
                          +     *     lock.tryLock(timeout, unit)) {
                          +     *   ...
                          +     * }}
                          * *

                          If the current thread * already holds this lock then the hold count is incremented by one and @@ -438,7 +438,6 @@ public class ReentrantLock implements Lock, java.io.Serializable { * the lock could be acquired * @throws InterruptedException if the current thread is interrupted * @throws NullPointerException if the time unit is null - * */ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { @@ -514,7 +513,7 @@ public class ReentrantLock implements Lock, java.io.Serializable { * not be entered with the lock already held then we can assert that * fact: * - *

                          +     *  
                           {@code
                                * class X {
                                *   ReentrantLock lock = new ReentrantLock();
                                *   // ...
                          @@ -527,8 +526,7 @@ public class ReentrantLock implements Lock, java.io.Serializable {
                                *       lock.unlock();
                                *     }
                                *   }
                          -     * }
                          -     * 
                          + * }}
                          * * @return the number of holds on this lock by the current thread, * or zero if this lock is not held by the current thread @@ -545,7 +543,7 @@ public class ReentrantLock implements Lock, java.io.Serializable { * testing. For example, a method that should only be called while * a lock is held can assert that this is the case: * - *
                          +     *  
                           {@code
                                * class X {
                                *   ReentrantLock lock = new ReentrantLock();
                                *   // ...
                          @@ -554,13 +552,12 @@ public class ReentrantLock implements Lock, java.io.Serializable {
                                *       assert lock.isHeldByCurrentThread();
                                *       // ... method body
                                *   }
                          -     * }
                          -     * 
                          + * }}
                          * *

                          It can also be used to ensure that a reentrant lock is used * in a non-reentrant manner, for example: * - *

                          +     *  
                           {@code
                                * class X {
                                *   ReentrantLock lock = new ReentrantLock();
                                *   // ...
                          @@ -574,8 +571,7 @@ public class ReentrantLock implements Lock, java.io.Serializable {
                                *           lock.unlock();
                                *       }
                                *   }
                          -     * }
                          -     * 
                          + * }}
                          * * @return {@code true} if current thread holds this lock and * {@code false} otherwise @@ -636,7 +632,6 @@ public class ReentrantLock implements Lock, java.io.Serializable { return sync.hasQueuedThreads(); } - /** * Queries whether the given thread is waiting to acquire this * lock. Note that because cancellations may occur at any time, a @@ -652,7 +647,6 @@ public class ReentrantLock implements Lock, java.io.Serializable { return sync.isQueued(thread); } - /** * Returns an estimate of the number of threads waiting to * acquire this lock. The value is only an estimate because the number of diff --git a/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java b/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java index fbafd3c5f..3698bab27 100644 --- a/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java +++ b/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java @@ -34,9 +34,8 @@ */ package java.util.concurrent.locks; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.Collection; /** * An implementation of {@link ReadWriteLock} supporting similar @@ -62,7 +61,7 @@ import java.util.*; *
                          Fair mode *
                          When constructed as fair, threads contend for entry using an * approximately arrival-order policy. When the currently held lock - * is released either the longest-waiting single writer thread will + * is released, either the longest-waiting single writer thread will * be assigned the write lock, or if there is a group of reader threads * waiting longer than all waiting writer threads, that group will be * assigned the read lock. @@ -80,8 +79,8 @@ import java.util.*; * will block unless both the read lock and write lock are free (which * implies there are no waiting threads). (Note that the non-blocking * {@link ReadLock#tryLock()} and {@link WriteLock#tryLock()} methods - * do not honor this fair setting and will acquire the lock if it is - * possible, regardless of waiting threads.) + * do not honor this fair setting and will immediately acquire the lock + * if it is possible, regardless of waiting threads.) *

                          * * @@ -143,21 +142,21 @@ import java.util.*; * void processCachedData() { * rwl.readLock().lock(); * if (!cacheValid) { - * // Must release read lock before acquiring write lock - * rwl.readLock().unlock(); - * rwl.writeLock().lock(); - * try { - * // Recheck state because another thread might have - * // acquired write lock and changed state before we did. - * if (!cacheValid) { - * data = ... - * cacheValid = true; - * } - * // Downgrade by acquiring read lock before releasing write lock - * rwl.readLock().lock(); - * } finally { - * rwl.writeLock().unlock(); // Unlock write, still hold read - * } + * // Must release read lock before acquiring write lock + * rwl.readLock().unlock(); + * rwl.writeLock().lock(); + * try { + * // Recheck state because another thread might have + * // acquired write lock and changed state before we did. + * if (!cacheValid) { + * data = ... + * cacheValid = true; + * } + * // Downgrade by acquiring read lock before releasing write lock + * rwl.readLock().lock(); + * } finally { + * rwl.writeLock().unlock(); // Unlock write, still hold read + * } * } * * try { @@ -176,33 +175,33 @@ import java.util.*; * is a class using a TreeMap that is expected to be large and * concurrently accessed. * - *

                          {@code
                          + *  
                           {@code
                            * class RWDictionary {
                          - *    private final Map m = new TreeMap();
                          - *    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
                          - *    private final Lock r = rwl.readLock();
                          - *    private final Lock w = rwl.writeLock();
                          + *   private final Map m = new TreeMap();
                          + *   private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
                          + *   private final Lock r = rwl.readLock();
                          + *   private final Lock w = rwl.writeLock();
                            *
                          - *    public Data get(String key) {
                          - *        r.lock();
                          - *        try { return m.get(key); }
                          - *        finally { r.unlock(); }
                          - *    }
                          - *    public String[] allKeys() {
                          - *        r.lock();
                          - *        try { return m.keySet().toArray(); }
                          - *        finally { r.unlock(); }
                          - *    }
                          - *    public Data put(String key, Data value) {
                          - *        w.lock();
                          - *        try { return m.put(key, value); }
                          - *        finally { w.unlock(); }
                          - *    }
                          - *    public void clear() {
                          - *        w.lock();
                          - *        try { m.clear(); }
                          - *        finally { w.unlock(); }
                          - *    }
                          + *   public Data get(String key) {
                          + *     r.lock();
                          + *     try { return m.get(key); }
                          + *     finally { r.unlock(); }
                          + *   }
                          + *   public String[] allKeys() {
                          + *     r.lock();
                          + *     try { return m.keySet().toArray(); }
                          + *     finally { r.unlock(); }
                          + *   }
                          + *   public Data put(String key, Data value) {
                          + *     w.lock();
                          + *     try { return m.put(key, value); }
                          + *     finally { w.unlock(); }
                          + *   }
                          + *   public void clear() {
                          + *     w.lock();
                          + *     try { m.clear(); }
                          + *     finally { w.unlock(); }
                          + *   }
                            * }}
                          * *

                          Implementation Notes

                          @@ -213,7 +212,6 @@ import java.util.*; * * @since 1.5 * @author Doug Lea - * */ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable { @@ -654,8 +652,7 @@ public class ReentrantReadWriteLock } /** - * Reconstitute this lock instance from a stream - * @param s the stream + * Reconstitutes the instance from a stream (that is, deserializes it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { @@ -799,7 +796,7 @@ public class ReentrantReadWriteLock * * @return {@code true} if the read lock was acquired */ - public boolean tryLock() { + public boolean tryLock() { return sync.tryReadLock(); } @@ -819,8 +816,11 @@ public class ReentrantReadWriteLock * permit barging on a fair lock then combine the timed and * un-timed forms together: * - *
                          if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
                          -         * 
                          + *
                           {@code
                          +         * if (lock.tryLock() ||
                          +         *     lock.tryLock(timeout, unit)) {
                          +         *   ...
                          +         * }}
                          * *

                          If the write lock is held by another thread then the * current thread becomes disabled for thread scheduling @@ -866,7 +866,6 @@ public class ReentrantReadWriteLock * @return {@code true} if the read lock was acquired * @throws InterruptedException if the current thread is interrupted * @throws NullPointerException if the time unit is null - * */ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { @@ -879,7 +878,7 @@ public class ReentrantReadWriteLock *

                          If the number of readers is now zero then the lock * is made available for write lock attempts. */ - public void unlock() { + public void unlock() { sync.releaseShared(1); } @@ -1049,8 +1048,11 @@ public class ReentrantReadWriteLock * that does permit barging on a fair lock then combine the * timed and un-timed forms together: * - *

                          if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
                          -         * 
                          + *
                           {@code
                          +         * if (lock.tryLock() ||
                          +         *     lock.tryLock(timeout, unit)) {
                          +         *   ...
                          +         * }}
                          * *

                          If the current thread already holds this lock then the * hold count is incremented by one and the method returns @@ -1108,7 +1110,6 @@ public class ReentrantReadWriteLock * * @throws InterruptedException if the current thread is interrupted * @throws NullPointerException if the time unit is null - * */ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { diff --git a/src/share/classes/java/util/concurrent/package-info.java b/src/share/classes/java/util/concurrent/package-info.java index 8116e82cf..4c56e0390 100644 --- a/src/share/classes/java/util/concurrent/package-info.java +++ b/src/share/classes/java/util/concurrent/package-info.java @@ -188,7 +188,7 @@ * A {@code CopyOnWriteArrayList} is preferable to a synchronized * {@code ArrayList} when the expected number of reads and traversals * greatly outnumber the number of updates to a list. - + * *

                          The "Concurrent" prefix used with some classes in this package * is a shorthand indicating several differences from similar * "synchronized" classes. For example {@code java.util.Hashtable} and @@ -218,9 +218,8 @@ * *

                          Memory Consistency Properties

                          * - * Chapter 17 of - * The Java™ Language Specification - * defines the + * + * Chapter 17 of the Java Language Specification defines the * happens-before relation on memory operations such as reads and * writes of shared variables. The results of a write by one thread are * guaranteed to be visible to a read by another thread only if the write -- GitLab