KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > EDU > oswego > cs > dl > util > concurrent > Sync


1 /*
2   File: Sync.java
3
4   Originally written by Doug Lea and released into the public domain.
5   This may be used for any purposes whatsoever without acknowledgment.
6   Thanks for the assistance and support of Sun Microsystems Labs,
7   and everyone contributing, testing, and using this code.
8
9   History:
10   Date Who What
11   11Jun1998 dl Create public version
12    5Aug1998 dl Added some convenient time constants
13 */

14
15 package EDU.oswego.cs.dl.util.concurrent;
16
17 /**
18  * Main interface for locks, gates, and conditions.
19  * <p>
20  * Sync objects isolate waiting and notification for particular
21  * logical states, resource availability, events, and the like that are
22  * shared across multiple threads. Use of Syncs sometimes
23  * (but by no means always) adds flexibility and efficiency
24  * compared to the use of plain java monitor methods
25  * and locking, and are sometimes (but by no means always)
26  * simpler to program with.
27  * <p>
28  *
29  * Most Syncs are intended to be used primarily (although
30  * not exclusively) in before/after constructions such as:
31  * <pre>
32  * class X {
33  * Sync gate;
34  * // ...
35  *
36  * public void m() {
37  * try {
38  * gate.acquire(); // block until condition holds
39  * try {
40  * // ... method body
41  * }
42  * finally {
43  * gate.release()
44  * }
45  * }
46  * catch (InterruptedException ex) {
47  * // ... evasive action
48  * }
49  * }
50  *
51  * public void m2(Sync cond) { // use supplied condition
52  * try {
53  * if (cond.attempt(10)) { // try the condition for 10 ms
54  * try {
55  * // ... method body
56  * }
57  * finally {
58  * cond.release()
59  * }
60  * }
61  * }
62  * catch (InterruptedException ex) {
63  * // ... evasive action
64  * }
65  * }
66  * }
67  * </pre>
68  * Syncs may be used in somewhat tedious but more flexible replacements
69  * for built-in Java synchronized blocks. For example:
70  * <pre>
71  * class HandSynched {
72  * private double state_ = 0.0;
73  * private final Sync lock; // use lock type supplied in constructor
74  * public HandSynched(Sync l) { lock = l; }
75  *
76  * public void changeState(double d) {
77  * try {
78  * lock.acquire();
79  * try { state_ = updateFunction(d); }
80  * finally { lock.release(); }
81  * }
82  * catch(InterruptedException ex) { }
83  * }
84  *
85  * public double getState() {
86  * double d = 0.0;
87  * try {
88  * lock.acquire();
89  * try { d = accessFunction(state_); }
90  * finally { lock.release(); }
91  * }
92  * catch(InterruptedException ex){}
93  * return d;
94  * }
95  * private double updateFunction(double d) { ... }
96  * private double accessFunction(double d) { ... }
97  * }
98  * </pre>
99  * If you have a lot of such methods, and they take a common
100  * form, you can standardize this using wrappers. Some of these
101  * wrappers are standardized in LockedExecutor, but you can make others.
102  * For example:
103  * <pre>
104  * class HandSynchedV2 {
105  * private double state_ = 0.0;
106  * private final Sync lock; // use lock type supplied in constructor
107  * public HandSynchedV2(Sync l) { lock = l; }
108  *
109  * protected void runSafely(Runnable r) {
110  * try {
111  * lock.acquire();
112  * try { r.run(); }
113  * finally { lock.release(); }
114  * }
115  * catch (InterruptedException ex) { // propagate without throwing
116  * Thread.currentThread().interrupt();
117  * }
118  * }
119  *
120  * public void changeState(double d) {
121  * runSafely(new Runnable() {
122  * public void run() { state_ = updateFunction(d); }
123  * });
124  * }
125  * // ...
126  * }
127  * </pre>
128  * <p>
129  * One reason to bother with such constructions is to use deadlock-
130  * avoiding back-offs when dealing with locks involving multiple objects.
131  * For example, here is a Cell class that uses attempt to back-off
132  * and retry if two Cells are trying to swap values with each other
133  * at the same time.
134  * <pre>
135  * class Cell {
136  * long value;
137  * Sync lock = ... // some sync implementation class
138  * void swapValue(Cell other) {
139  * for (;;) {
140  * try {
141  * lock.acquire();
142  * try {
143  * if (other.lock.attempt(100)) {
144  * try {
145  * long t = value;
146  * value = other.value;
147  * other.value = t;
148  * return;
149  * }
150  * finally { other.lock.release(); }
151  * }
152  * }
153  * finally { lock.release(); }
154  * }
155  * catch (InterruptedException ex) { return; }
156  * }
157  * }
158  * }
159  *</pre>
160  * <p>
161  * Here is an even fancier version, that uses lock re-ordering
162  * upon conflict:
163  * <pre>
164  * class Cell {
165  * long value;
166  * Sync lock = ...;
167  * private static boolean trySwap(Cell a, Cell b) {
168  * a.lock.acquire();
169  * try {
170  * if (!b.lock.attempt(0))
171  * return false;
172  * try {
173  * long t = a.value;
174  * a.value = b.value;
175  * b.value = t;
176  * return true;
177  * }
178  * finally { other.lock.release(); }
179  * }
180  * finally { lock.release(); }
181  * return false;
182  * }
183  *
184  * void swapValue(Cell other) {
185  * try {
186  * while (!trySwap(this, other) &&
187  * !tryswap(other, this))
188  * Thread.sleep(1);
189  * }
190  * catch (InterruptedException ex) { return; }
191  * }
192  *}
193  *</pre>
194  * <p>
195  * Interruptions are in general handled as early as possible.
196  * Normally, InterruptionExceptions are thrown
197  * in acquire and attempt(msec) if interruption
198  * is detected upon entry to the method, as well as in any
199  * later context surrounding waits.
200  * However, interruption status is ignored in release();
201  * <p>
202  * Timed versions of attempt report failure via return value.
203  * If so desired, you can transform such constructions to use exception
204  * throws via
205  * <pre>
206  * if (!c.attempt(timeval)) throw new TimeoutException(timeval);
207  * </pre>
208  * <p>
209  * The TimoutSync wrapper class can be used to automate such usages.
210  * <p>
211  * All time values are expressed in milliseconds as longs, which have a maximum
212  * value of Long.MAX_VALUE, or almost 300,000 centuries. It is not
213  * known whether JVMs actually deal correctly with such extreme values.
214  * For convenience, some useful time values are defined as static constants.
215  * <p>
216  * All implementations of the three Sync methods guarantee to
217  * somehow employ Java <code>synchronized</code> methods or blocks,
218  * and so entail the memory operations described in JLS
219  * chapter 17 which ensure that variables are loaded and flushed
220  * within before/after constructions.
221  * <p>
222  * Syncs may also be used in spinlock constructions. Although
223  * it is normally best to just use acquire(), various forms
224  * of busy waits can be implemented. For a simple example
225  * (but one that would probably never be preferable to using acquire()):
226  * <pre>
227  * class X {
228  * Sync lock = ...
229  * void spinUntilAcquired() throws InterruptedException {
230  * // Two phase.
231  * // First spin without pausing.
232  * int purespins = 10;
233  * for (int i = 0; i < purespins; ++i) {
234  * if (lock.attempt(0))
235  * return true;
236  * }
237  * // Second phase - use timed waits
238  * long waitTime = 1; // 1 millisecond
239  * for (;;) {
240  * if (lock.attempt(waitTime))
241  * return true;
242  * else
243  * waitTime = waitTime * 3 / 2 + 1; // increase 50%
244  * }
245  * }
246  * }
247  * </pre>
248  * <p>
249  * In addition pure synchronization control, Syncs
250  * may be useful in any context requiring before/after methods.
251  * For example, you can use an ObservableSync
252  * (perhaps as part of a LayeredSync) in order to obtain callbacks
253  * before and after each method invocation for a given class.
254  * <p>
255
256  * <p>[<a HREF="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
257 **/

258
259
260 public interface Sync {
261
262   /**
263    * Wait (possibly forever) until successful passage.
264    * Fail only upon interuption. Interruptions always result in
265    * `clean' failures. On failure, you can be sure that it has not
266    * been acquired, and that no
267    * corresponding release should be performed. Conversely,
268    * a normal return guarantees that the acquire was successful.
269   **/

270
271   public void acquire() throws InterruptedException JavaDoc;
272
273   /**
274    * Wait at most msecs to pass; report whether passed.
275    * <p>
276    * The method has best-effort semantics:
277    * The msecs bound cannot
278    * be guaranteed to be a precise upper bound on wait time in Java.
279    * Implementations generally can only attempt to return as soon as possible
280    * after the specified bound. Also, timers in Java do not stop during garbage
281    * collection, so timeouts can occur just because a GC intervened.
282    * So, msecs arguments should be used in
283    * a coarse-grained manner. Further,
284    * implementations cannot always guarantee that this method
285    * will return at all without blocking indefinitely when used in
286    * unintended ways. For example, deadlocks may be encountered
287    * when called in an unintended context.
288    * <p>
289    * @param msecs the number of milleseconds to wait.
290    * An argument less than or equal to zero means not to wait at all.
291    * However, this may still require
292    * access to a synchronization lock, which can impose unbounded
293    * delay if there is a lot of contention among threads.
294    * @return true if acquired
295   **/

296
297   public boolean attempt(long msecs) throws InterruptedException JavaDoc;
298
299   /**
300    * Potentially enable others to pass.
301    * <p>
302    * Because release does not raise exceptions,
303    * it can be used in `finally' clauses without requiring extra
304    * embedded try/catch blocks. But keep in mind that
305    * as with any java method, implementations may
306    * still throw unchecked exceptions such as Error or NullPointerException
307    * when faced with uncontinuable errors. However, these should normally
308    * only be caught by higher-level error handlers.
309   **/

310
311   public void release();
312
313   /** One second, in milliseconds; convenient as a time-out value **/
314   public static final long ONE_SECOND = 1000;
315
316   /** One minute, in milliseconds; convenient as a time-out value **/
317   public static final long ONE_MINUTE = 60 * ONE_SECOND;
318
319   /** One hour, in milliseconds; convenient as a time-out value **/
320   public static final long ONE_HOUR = 60 * ONE_MINUTE;
321
322   /** One day, in milliseconds; convenient as a time-out value **/
323   public static final long ONE_DAY = 24 * ONE_HOUR;
324
325   /** One week, in milliseconds; convenient as a time-out value **/
326   public static final long ONE_WEEK = 7 * ONE_DAY;
327
328   /** One year in milliseconds; convenient as a time-out value **/
329   // Not that it matters, but there is some variation across
330
// standard sources about value at msec precision.
331
// The value used is the same as in java.util.GregorianCalendar
332
public static final long ONE_YEAR = (long)(365.2425 * ONE_DAY);
333
334   /** One century in milliseconds; convenient as a time-out value **/
335   public static final long ONE_CENTURY = 100 * ONE_YEAR;
336
337
338 }
339
340
341
Popular Tags