KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > util > concurrent > locks > ReentrantLock


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
3  * notice. All rights reserved.
4  */

5 package com.tc.util.concurrent.locks;
6
7 import com.tc.exception.TCNotSupportedMethodException;
8 import com.tc.exception.TCRuntimeException;
9 import com.tc.object.bytecode.ManagerUtil;
10 import com.tc.object.lockmanager.api.LockLevel;
11 import com.tc.util.Stack;
12 import com.tc.util.UnsafeUtil;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.Date JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Map JavaDoc;
20 import java.util.concurrent.TimeUnit JavaDoc;
21 import java.util.concurrent.locks.AbstractQueuedSynchronizer JavaDoc;
22 import java.util.concurrent.locks.Condition JavaDoc;
23 import java.util.concurrent.locks.Lock JavaDoc;
24
25 public class ReentrantLock implements Lock JavaDoc, java.io.Serializable JavaDoc {
26   private boolean isFair;
27
28   /** Current owner thread */
29   transient Thread JavaDoc owner = null;
30   transient int numOfHolds = 0;
31   transient List JavaDoc waitingQueue = new ArrayList JavaDoc();
32   transient int state = 0;
33   transient int numQueued = 0;
34   transient Stack lockInUnShared = new Stack();
35
36   transient Object JavaDoc lock = new Object JavaDoc();
37
38   public ReentrantLock() {
39     this.isFair = false;
40
41     initialize();
42   }
43
44   public ReentrantLock(boolean fair) {
45     this.isFair = fair;
46
47     initialize();
48   }
49
50   private void initialize() {
51     this.owner = null;
52     this.numOfHolds = 0;
53     this.waitingQueue = new ArrayList JavaDoc();
54     this.state = 0;
55     this.numQueued = 0;
56     this.lock = new Object JavaDoc();
57     this.lockInUnShared = new Stack();
58   }
59
60   public void lock() {
61     Thread JavaDoc currentThread = Thread.currentThread();
62     synchronized (lock) {
63       while (owner != null && owner != currentThread && lockInUnShared.contains(Boolean.TRUE)) {
64         try {
65           lock.wait();
66         } catch (InterruptedException JavaDoc e) {
67           throw new TCRuntimeException(e);
68         }
69       }
70
71       waitingQueue.add(currentThread);
72       numQueued++;
73     }
74
75     ManagerUtil.monitorEnter(this, LockLevel.WRITE);
76     UnsafeUtil.monitorEnter(this);
77
78     synchronized (lock) {
79       innerSetLockState();
80       waitingQueue.remove(currentThread);
81       numQueued--;
82     }
83   }
84
85   public void lockInterruptibly() throws InterruptedException JavaDoc {
86     if (Thread.interrupted()) throw new InterruptedException JavaDoc();
87     lock();
88     if (Thread.interrupted()) {
89       if (isHeldByCurrentThread()) {
90         unlock();
91       }
92       throw new InterruptedException JavaDoc();
93     }
94   }
95
96   public boolean tryLock() {
97     boolean canLock = false;
98     synchronized (lock) {
99       canLock = canProceedToLock();
100       if (ManagerUtil.isManaged(this) && canLock) {
101         canLock = ManagerUtil.tryMonitorEnter(this, LockLevel.WRITE);
102         if (canLock) {
103           UnsafeUtil.monitorEnter(this);
104         }
105       } else {
106         if (canLock) {
107           UnsafeUtil.monitorEnter(this);
108         }
109       }
110       if (canLock) {
111         innerSetLockState();
112       }
113       return canLock;
114     }
115   }
116
117   public boolean tryLock(long timeout, TimeUnit JavaDoc unit) throws InterruptedException JavaDoc {
118     if (!tryLock()) {
119       Thread JavaDoc currentThread = Thread.currentThread();
120
121       long timeoutInNanos = TimeUnit.NANOSECONDS.convert(50, TimeUnit.MILLISECONDS);
122       long totalTimeoutInNanos = unit.toNanos(timeout);
123
124       if (timeoutInNanos > totalTimeoutInNanos) {
125         timeoutInNanos = totalTimeoutInNanos;
126       }
127
128       synchronized (lock) {
129         boolean locked = false;
130
131         while (!locked && totalTimeoutInNanos > 0) {
132           waitingQueue.add(currentThread);
133           numQueued++;
134
135           TimeUnit.NANOSECONDS.timedWait(lock, timeoutInNanos);
136           totalTimeoutInNanos -= timeoutInNanos;
137
138           waitingQueue.remove(currentThread);
139           numQueued--;
140
141           locked = tryLock();
142         }
143         return locked;
144       }
145     }
146     return true;
147   }
148
149   public void unlock() {
150     boolean needDSOUnlock = false;
151     synchronized (lock) {
152       boolean isLockedInUnSharedMode = ((Boolean JavaDoc) this.lockInUnShared.pop()).booleanValue();
153       needDSOUnlock = !isLockedInUnSharedMode && ManagerUtil.isManaged(this) && !ManagerUtil.isCreationInProgress();
154
155       if (--numOfHolds == 0) {
156         owner = null;
157         setState(0);
158         this.lockInUnShared.remove(Thread.currentThread());
159       }
160       UnsafeUtil.monitorExit(this);
161       if (needDSOUnlock) {
162         ManagerUtil.monitorExit(this);
163       } else {
164         lock.notifyAll();
165       }
166     }
167   }
168
169   public Condition JavaDoc newCondition() {
170     return new ConditionObject(new SyncCondition(), this);
171   }
172
173   public int getHoldCount() {
174     return (owner == Thread.currentThread()) ? numOfHolds : 0;
175   }
176
177   public boolean isHeldByCurrentThread() {
178     Thread JavaDoc owner = null;
179     int state = 0;
180     synchronized (lock) {
181       owner = this.owner;
182       state = getState();
183     }
184     return state != 0 && owner == Thread.currentThread();
185   }
186
187   public boolean isLocked() {
188     if (ManagerUtil.isManaged(this)) {
189       return isHeldByCurrentThread() || ManagerUtil.isLocked(this);
190     } else {
191       return getState() > 0;
192     }
193   }
194
195   public final boolean isFair() {
196     return isFair;
197   }
198
199   protected Thread JavaDoc getOwner() {
200     if (ManagerUtil.isManaged(this)) {
201       throw new TCNotSupportedMethodException();
202     } else {
203       return (numOfHolds == 0) ? null : owner;
204     }
205   }
206
207   public final boolean hasQueuedThreads() {
208     if (ManagerUtil.isManaged(this)) {
209       return ManagerUtil.queueLength(this) > 0;
210     } else {
211       return numQueued > 0;
212     }
213   }
214
215   public final boolean hasQueuedThread(Thread JavaDoc thread) {
216     if (ManagerUtil.isManaged(this)) {
217       throw new TCNotSupportedMethodException();
218     } else {
219       List JavaDoc waitingThreads = null;
220       synchronized (lock) {
221         waitingThreads = waitingQueue;
222       }
223       return waitingThreads.contains(thread);
224     }
225   }
226
227   public final int getQueueLength() {
228     if (ManagerUtil.isManaged(this)) {
229       return ManagerUtil.queueLength(this);
230     } else {
231       return numQueued;
232     }
233   }
234
235   protected Collection JavaDoc getQueuedThreads() {
236     if (ManagerUtil.isManaged(this)) {
237       throw new TCNotSupportedMethodException();
238     } else {
239       List JavaDoc waitingThreads = null;
240       synchronized (lock) {
241         waitingThreads = waitingQueue;
242       }
243       return waitingThreads;
244     }
245   }
246
247   public boolean hasWaiters(Condition JavaDoc condition) {
248     if (condition == null) throw new NullPointerException JavaDoc();
249     if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject JavaDoc)) throw new IllegalArgumentException JavaDoc(
250                                                                                                                "not owner");
251     return false;
252   }
253
254   public int getWaitQueueLength(Condition JavaDoc condition) {
255     if (condition == null) throw new NullPointerException JavaDoc();
256     if (!(condition instanceof ConditionObject)) throw new IllegalArgumentException JavaDoc("not owner");
257     return ((ConditionObject) condition).getWaitQueueLength(this);
258   }
259
260   protected Collection JavaDoc getWaitingThreads(Condition JavaDoc condition) {
261     if (ManagerUtil.isManaged(this)) throw new TCNotSupportedMethodException();
262
263     if (condition == null) throw new NullPointerException JavaDoc();
264     if (!(condition instanceof ConditionObject)) throw new IllegalArgumentException JavaDoc("not owner");
265     return ((ConditionObject) condition).getWaitingThreads(this);
266   }
267
268   private String JavaDoc getLockState() {
269     return (isLocked() ? (isHeldByCurrentThread() ? "[Locally locked]" : "[Remotelly locked]") : "[Unlocked]");
270   }
271
272   public String JavaDoc toString() {
273     Thread JavaDoc owner = null;
274     return ManagerUtil.isManaged(this) ? (new StringBuilder JavaDoc()).append(super.toString()).append(getLockState())
275         .toString() : (new StringBuilder JavaDoc()).append(super.toString())
276         .append(
277                 (owner = getOwner()) != null ? (new StringBuilder JavaDoc()).append("[Locked by thread ")
278                     .append(owner.getName()).append("]").toString() : "[Unlocked]").toString();
279
280   }
281
282   private boolean canProceedToLock() {
283     boolean canLock = waitingQueue.isEmpty() && (getState() == 0);
284     return (owner == null && canLock) || (owner == Thread.currentThread());
285   }
286
287   private void innerSetLockState() {
288     if (!ManagerUtil.isManaged(ReentrantLock.this)
289         || !ManagerUtil.isHeldByCurrentThread(ReentrantLock.this, LockLevel.WRITE)) {
290       this.lockInUnShared.push(Boolean.TRUE);
291     } else {
292       this.lockInUnShared.push(Boolean.FALSE);
293     }
294
295     owner = Thread.currentThread();
296     numOfHolds++;
297     setState(1);
298   }
299
300   private void setState(int state) {
301     this.state = state;
302   }
303
304   private int getState() {
305     return this.state;
306   }
307
308   private void readObject(java.io.ObjectInputStream JavaDoc s) throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
309     s.defaultReadObject();
310     isFair = s.readBoolean();
311     initialize();
312   }
313
314   private void writeObject(java.io.ObjectOutputStream JavaDoc s) throws java.io.IOException JavaDoc {
315     s.defaultWriteObject();
316     s.writeBoolean(isFair);
317   }
318
319   private static class SyncCondition implements java.io.Serializable JavaDoc {
320     public SyncCondition() {
321       super();
322     }
323   }
324
325   private static class ConditionObject implements Condition JavaDoc, java.io.Serializable JavaDoc {
326     private static final int SIGNALLED = 1;
327     private static final int NOT_SIGNALLED = 0;
328
329     private transient List JavaDoc waitingThreads;
330     private transient int numOfWaitingThreards;
331     private transient Map JavaDoc waitOnUnshared;
332
333     private final ReentrantLock originalLock;
334     private final Object JavaDoc realCondition;
335     private int signal = NOT_SIGNALLED;
336
337     private static long getSystemNanos() {
338       return System.nanoTime();
339     }
340
341     public ConditionObject(Object JavaDoc realCondition, ReentrantLock originalLock) {
342       this.originalLock = originalLock;
343       this.realCondition = realCondition;
344       this.waitingThreads = new ArrayList JavaDoc();
345       this.numOfWaitingThreards = 0;
346       this.waitOnUnshared = new HashMap JavaDoc();
347     }
348
349     public ConditionObject() {
350       this.originalLock = null;
351       this.realCondition = null;
352       this.waitingThreads = new ArrayList JavaDoc();
353       this.numOfWaitingThreards = 0;
354       this.waitOnUnshared = new HashMap JavaDoc();
355     }
356
357     private void fullRelease() {
358       if (originalLock.getHoldCount() > 0) {
359         while (originalLock.getHoldCount() > 0) {
360           originalLock.unlock();
361         }
362       } else {
363         // The else part is needed only when the await of the Condition object is executed
364
// in an applicator as ManagerUtil.monitorEnter() is short circuited in applicator.
365
while (Thread.holdsLock(originalLock)) {
366           UnsafeUtil.monitorExit(originalLock);
367         }
368       }
369     }
370
371     private void reacquireLock(int numOfHolds) {
372       if (originalLock.getHoldCount() >= numOfHolds) { return; }
373       while (originalLock.getHoldCount() < numOfHolds) {
374         originalLock.lock();
375       }
376     }
377
378     private void checkCauseAndThrowInterruptedExceptionIfNecessary(TCRuntimeException e) throws InterruptedException JavaDoc {
379       if (e.getCause() instanceof InterruptedException JavaDoc) {
380         throw (InterruptedException JavaDoc) e.getCause();
381       } else {
382         throw e;
383       }
384     }
385
386     private void checkCauseAndIgnoreInterruptedException(TCRuntimeException e) {
387       if (!(e.getCause() instanceof InterruptedException JavaDoc)) { throw e; }
388     }
389
390     private void addWaitOnUnshared() {
391       waitOnUnshared.put(Thread.currentThread(), ManagerUtil.isManaged(realCondition) ? Boolean.FALSE : Boolean.TRUE);
392     }
393
394     private boolean isLockRealConditionInUnshared() {
395       if (!ManagerUtil.isManaged(realCondition) || !ManagerUtil.isHeldByCurrentThread(realCondition, LockLevel.WRITE)) { return true; }
396       return false;
397     }
398
399     public void await() throws InterruptedException JavaDoc {
400       Thread JavaDoc currentThread = Thread.currentThread();
401
402       if (!originalLock.isHeldByCurrentThread()) { throw new IllegalMonitorStateException JavaDoc(); }
403       if (Thread.interrupted()) { throw new InterruptedException JavaDoc(); }
404
405       int numOfHolds = originalLock.getHoldCount();
406       try {
407         ManagerUtil.monitorEnter(realCondition, LockLevel.WRITE);
408         UnsafeUtil.monitorEnter(realCondition);
409         boolean isLockInUnshared = isLockRealConditionInUnshared();
410         try {
411           fullRelease();
412
413           waitingThreads.add(currentThread);
414           numOfWaitingThreards++;
415
416           addWaitOnUnshared();
417           try {
418             ManagerUtil.objectWait0(realCondition);
419           } finally {
420             waitOnUnshared.remove(currentThread);
421             waitingThreads.remove(currentThread);
422             numOfWaitingThreards--;
423           }
424         } finally {
425           UnsafeUtil.monitorExit(realCondition);
426           if (!isLockInUnshared) {
427             ManagerUtil.monitorExit(realCondition);
428           }
429         }
430       } catch (TCRuntimeException e) {
431         checkCauseAndThrowInterruptedExceptionIfNecessary(e);
432       } finally {
433         reacquireLock(numOfHolds);
434       }
435     }
436
437     public void awaitUninterruptibly() {
438       Thread JavaDoc currentThread = Thread.currentThread();
439
440       if (!originalLock.isHeldByCurrentThread()) { throw new IllegalMonitorStateException JavaDoc(); }
441
442       int numOfHolds = originalLock.getHoldCount();
443       boolean isInterrupted = false;
444       try {
445         ManagerUtil.monitorEnter(realCondition, LockLevel.WRITE);
446         UnsafeUtil.monitorEnter(realCondition);
447         boolean isLockInUnshared = isLockRealConditionInUnshared();
448         try {
449           fullRelease();
450           signal = NOT_SIGNALLED;
451           while (signal == NOT_SIGNALLED) {
452             waitingThreads.add(currentThread);
453             numOfWaitingThreards++;
454
455             addWaitOnUnshared();
456             try {
457               ManagerUtil.objectWait0(realCondition);
458             } catch (InterruptedException JavaDoc e) {
459               isInterrupted = true;
460             } finally {
461               waitOnUnshared.remove(currentThread);
462               waitingThreads.remove(currentThread);
463               numOfWaitingThreards--;
464             }
465           }
466         } finally {
467           UnsafeUtil.monitorExit(realCondition);
468           if (!isLockInUnshared) {
469             ManagerUtil.monitorExit(realCondition);
470           }
471         }
472       } finally {
473         reacquireLock(numOfHolds);
474       }
475
476       if (isInterrupted) {
477         currentThread.interrupt();
478       }
479     }
480
481     public long awaitNanos(long nanosTimeout) throws InterruptedException JavaDoc {
482       Thread JavaDoc currentThread = Thread.currentThread();
483
484       if (!originalLock.isHeldByCurrentThread()) { throw new IllegalMonitorStateException JavaDoc(); }
485       if (Thread.interrupted()) { throw new InterruptedException JavaDoc(); }
486
487       int numOfHolds = originalLock.getHoldCount();
488       try {
489         ManagerUtil.monitorEnter(realCondition, LockLevel.WRITE);
490         UnsafeUtil.monitorEnter(realCondition);
491         boolean isLockInUnshared = isLockRealConditionInUnshared();
492         try {
493           fullRelease();
494           waitingThreads.add(currentThread);
495           numOfWaitingThreards++;
496
497           addWaitOnUnshared();
498           try {
499             long startTime = getSystemNanos();
500             TimeUnit.NANOSECONDS.timedWait(realCondition, nanosTimeout);
501             long remainingTime = nanosTimeout - (getSystemNanos() - startTime);
502             return remainingTime;
503           } finally {
504             waitOnUnshared.remove(currentThread);
505             waitingThreads.remove(currentThread);
506             numOfWaitingThreards--;
507           }
508         } finally {
509           UnsafeUtil.monitorExit(realCondition);
510           if (!isLockInUnshared) {
511             ManagerUtil.monitorExit(realCondition);
512           }
513         }
514       } catch (TCRuntimeException e) {
515         checkCauseAndThrowInterruptedExceptionIfNecessary(e);
516         return 0;
517       } finally {
518         reacquireLock(numOfHolds);
519       }
520     }
521
522     public boolean await(long time, TimeUnit JavaDoc unit) throws InterruptedException JavaDoc {
523       if (unit == null) { throw new NullPointerException JavaDoc(); }
524       return awaitNanos(unit.toNanos(time)) > 0;
525     }
526
527     public boolean awaitUntil(Date JavaDoc deadline) throws InterruptedException JavaDoc {
528       if (deadline == null) { throw new NullPointerException JavaDoc(); }
529
530       long abstime = deadline.getTime();
531       if (System.currentTimeMillis() > abstime) { return true; }
532       return !await(abstime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
533     }
534
535     private boolean hasWaitOnUnshared() {
536       return waitOnUnshared.values().contains(Boolean.TRUE);
537     }
538
539     public void signal() {
540       if (!originalLock.isHeldByCurrentThread()) { throw new IllegalMonitorStateException JavaDoc(); }
541
542       ManagerUtil.monitorEnter(realCondition, LockLevel.WRITE);
543       UnsafeUtil.monitorEnter(realCondition);
544       boolean isLockInUnshared = isLockRealConditionInUnshared();
545       try {
546         ManagerUtil.objectNotify(realCondition);
547         if (hasWaitOnUnshared()) {
548           realCondition.notify();
549         }
550         signal = SIGNALLED;
551       } finally {
552         UnsafeUtil.monitorExit(realCondition);
553         if (!isLockInUnshared) {
554           ManagerUtil.monitorExit(realCondition);
555         }
556       }
557
558     }
559
560     public void signalAll() {
561       if (!originalLock.isHeldByCurrentThread()) { throw new IllegalMonitorStateException JavaDoc(); }
562       ManagerUtil.monitorEnter(realCondition, LockLevel.WRITE);
563       UnsafeUtil.monitorEnter(realCondition);
564       boolean isLockInUnshared = isLockRealConditionInUnshared();
565       try {
566         ManagerUtil.objectNotifyAll(realCondition);
567         if (hasWaitOnUnshared()) {
568           realCondition.notifyAll();
569         }
570         signal = SIGNALLED;
571       } finally {
572         UnsafeUtil.monitorExit(realCondition);
573         if (!isLockInUnshared) {
574           ManagerUtil.monitorExit(realCondition);
575         }
576       }
577     }
578
579     int getWaitQueueLength(ReentrantLock lock) {
580       if (originalLock != lock) throw new IllegalArgumentException JavaDoc("not owner");
581       if (!ManagerUtil.isManaged(originalLock)) {
582         return numOfWaitingThreards;
583       } else {
584         return ManagerUtil.waitLength(realCondition);
585       }
586     }
587
588     Collection JavaDoc getWaitingThreads(ReentrantLock lock) {
589       if (originalLock != lock) throw new IllegalArgumentException JavaDoc("not owner");
590       return waitingThreads;
591     }
592
593     private void readObject(java.io.ObjectInputStream JavaDoc s) throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
594       s.defaultReadObject();
595       this.waitingThreads = new ArrayList JavaDoc();
596       this.numOfWaitingThreards = 0;
597       this.waitOnUnshared = new HashMap JavaDoc();
598       this.signal = NOT_SIGNALLED;
599     }
600
601     private void writeObject(java.io.ObjectOutputStream JavaDoc s) throws java.io.IOException JavaDoc {
602       s.defaultWriteObject();
603     }
604
605   }
606 }
607
Popular Tags