Code - Class EDU.oswego.cs.dl.util.concurrent.Mutex


1 /*
2   File: Mutex.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 */

13
14 package EDU.oswego.cs.dl.util.concurrent;
15
16 /**
17  * A simple non-reentrant mutual exclusion lock.
18  * The lock is free upon construction. Each acquire gets the
19  * lock, and each release frees it. Releasing a lock that
20  * is already free has no effect.
21  * <p>
22  * This implementation makes no attempt to provide any fairness
23  * or ordering guarantees. If you need them, consider using one of
24  * the Semaphore implementations as a locking mechanism.
25  * <p>
26  * <b>Sample usage</b><br>
27  * <p>
28  * Mutex can be useful in constructions that cannot be
29  * expressed using java synchronized blocks because the
30  * acquire/release pairs do not occur in the same method or
31  * code block. For example, you can use them for hand-over-hand
32  * locking across the nodes of a linked list. This allows
33  * extremely fine-grained locking, and so increases
34  * potential concurrency, at the cost of additional complexity and
35  * overhead that would normally make this worthwhile only in cases of
36  * extreme contention.
37  * <pre>
38  * class Node {
39  * Object item;
40  * Node next;
41  * Mutex lock = new Mutex(); // each node keeps its own lock
42  *
43  * Node(Object x, Node n) { item = x; next = n; }
44  * }
45  *
46  * class List {
47  * protected Node head; // pointer to first node of list
48  *
49  * // Use plain java synchronization to protect head field.
50  * // (We could instead use a Mutex here too but there is no
51  * // reason to do so.)
52  * protected synchronized Node getHead() { return head; }
53  *
54  * boolean search(Object x) throws InterruptedException {
55  * Node p = getHead();
56  * if (p == null) return false;
57  *
58  * // (This could be made more compact, but for clarity of illustration,
59  * // all of the cases that can arise are handled separately.)
60  *
61  * p.lock.acquire(); // Prime loop by acquiring first lock.
62  * // (If the acquire fails due to
63  * // interrupt, the method will throw
64  * // InterruptedException now,
65  * // so there is no need for any
66  * // further cleanup.)
67  * for (;;) {
68  * if (x.equals(p.item)) {
69  * p.lock.release(); // release current before return
70  * return true;
71  * }
72  * else {
73  * Node nextp = p.next;
74  * if (nextp == null) {
75  * p.lock.release(); // release final lock that was held
76  * return false;
77  * }
78  * else {
79  * try {
80  * nextp.lock.acquire(); // get next lock before releasing current
81  * }
82  * catch (InterruptedException ex) {
83  * p.lock.release(); // also release current if acquire fails
84  * throw ex;
85  * }
86  * p.lock.release(); // release old lock now that new one held
87  * p = nextp;
88  * }
89  * }
90  * }
91  * }
92  *
93  * synchronized void add(Object x) { // simple prepend
94  * // The use of `synchronized' here protects only head field.
95  * // The method does not need to wait out other traversers
96  * // who have already made it past head.
97  *
98  * head = new Node(x, head);
99  * }
100  *
101  * // ... other similar traversal and update methods ...
102  * }
103  * </pre>
104  * <p>
105  * @see Semaphore
106  * <p>[<a HREF="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
107 **/

108
109 public class Mutex implements Sync {
110
111   /** The lock status **/
112   protected boolean inuse_ = false;
113
114   public void acquire() throws InterruptedException {
115     if (Thread.interrupted()) throw new InterruptedException();
116     synchronized(this) {
117       try {
118         while (inuse_) wait();
119         inuse_ = true;
120       }
121       catch (InterruptedException ex) {
122         notify();
123         throw ex;
124       }
125     }
126   }
127
128   public synchronized void release() {
129     inuse_ = false;
130     notify();
131   }
132
133
134   public boolean attempt(long msecs) throws InterruptedException {
135     if (Thread.interrupted()) throw new InterruptedException();
136     synchronized(this) {
137       if (!inuse_) {
138         inuse_ = true;
139         return true;
140       }
141       else if (msecs <= 0)
142         return false;
143       else {
144         long waitTime = msecs;
145         long start = System.currentTimeMillis();
146         try {
147           for (;;) {
148             wait(waitTime);
149             if (!inuse_) {
150               inuse_ = true;
151               return true;
152             }
153             else {
154               waitTime = msecs - (System.currentTimeMillis() - start);
155               if (waitTime <= 0)
156                 return false;
157             }
158           }
159         }
160         catch (InterruptedException ex) {
161           notify();
162           throw ex;
163         }
164       }
165     }
166   }
167
168 }
169
170

Java API By Example, From Geeks To Geeks. | Conditions of Use | About Us © 2002 - 2005, KickJava.com, or its affiliates