Mercurial > hg > blitz_condensed
comparison src/EDU/oswego/cs/dl/util/concurrent/Mutex.java @ 0:3dc0c5604566
Initial checkin of blitz 2.0 fcs - no installer yet.
author | Dan Creswell <dan.creswell@gmail.com> |
---|---|
date | Sat, 21 Mar 2009 11:00:06 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3dc0c5604566 |
---|---|
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 if (inuse_ == false) | |
130 throw new RuntimeException("Not locked!!!!"); | |
131 inuse_ = false; | |
132 notify(); | |
133 } | |
134 | |
135 | |
136 public boolean attempt(long msecs) throws InterruptedException { | |
137 // if (Thread.interrupted()) throw new InterruptedException(); | |
138 synchronized(this) { | |
139 if (!inuse_) { | |
140 inuse_ = true; | |
141 return true; | |
142 } | |
143 else if (msecs <= 0) | |
144 return false; | |
145 else { | |
146 long waitTime = msecs; | |
147 long start = System.currentTimeMillis(); | |
148 try { | |
149 for (;;) { | |
150 wait(waitTime); | |
151 if (!inuse_) { | |
152 inuse_ = true; | |
153 return true; | |
154 } | |
155 else { | |
156 waitTime = msecs - (System.currentTimeMillis() - start); | |
157 if (waitTime <= 0) | |
158 return false; | |
159 } | |
160 } | |
161 } | |
162 catch (InterruptedException ex) { | |
163 notify(); | |
164 throw ex; | |
165 } | |
166 } | |
167 } | |
168 } | |
169 | |
170 } | |
171 |