| ||||
|
Code - Class EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock1 /* 2 File: ReentrantWriterPreferenceReadWriteLock.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 26aug1998 dl Create public version 12 7sep2000 dl Readers are now also reentrant 13 19jan2001 dl Allow read->write upgrades if the only reader 14 10dec2002 dl Throw IllegalStateException on extra release 15 */ 16 17 package EDU.oswego.cs.dl.util.concurrent; 18 import java.util.*; 19 20 /** 21 * A writer-preference ReadWriteLock that allows both readers and 22 * writers to reacquire 23 * read or write locks in the style of a ReentrantLock. 24 * Readers are not allowed until all write locks held by 25 * the writing thread have been released. 26 * Among other applications, reentrancy can be useful when 27 * write locks are held during calls or callbacks to methods that perform 28 * reads under read locks. 29 * <p> 30 * <b>Sample usage</b>. Here is a code sketch showing how to exploit 31 * reentrancy to perform lock downgrading after updating a cache: 32 * <pre> 33 * class CachedData { 34 * Object data; 35 * volatile boolean cacheValid; 36 * ReentrantWriterPreferenceReadWriteLock rwl = ... 37 * 38 * void processCachedData() { 39 * rwl.readLock().acquire(); 40 * if (!cacheValid) { 41 * 42 * // upgrade lock: 43 * rwl.readLock().release(); // must release first to obtain writelock 44 * rwl.writeLock().acquire(); 45 * if (!cacheValid) { // recheck 46 * data = ... 47 * cacheValid = true; 48 * } 49 * // downgrade lock 50 * rwl.readLock().acquire(); // reacquire read without giving up lock 51 * rwl.writeLock().release(); // release write, still hold read 52 * } 53 * 54 * use(data); 55 * rwl.readLock().release(); 56 * } 57 * } 58 * </pre> 59 * 60 * 61 * <p>[<a HREF="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>] 62 * @see ReentrantLock 63 **/ 64 65 public class ReentrantWriterPreferenceReadWriteLock extends WriterPreferenceReadWriteLock { 66 67 /** Number of acquires on write lock by activeWriter_ thread **/ 68 protected long writeHolds_ = 0; 69 70 /** Number of acquires on read lock by any reader thread **/ 71 protected HashMap readers_ = new HashMap(); 72 73 /** cache/reuse the special Integer value one to speed up readlocks **/ 74 protected static final Integer IONE = new Integer(1); 75 76 77 protected boolean allowReader() { 78 return (activeWriter_ == null && waitingWriters_ == 0) || 79 activeWriter_ == Thread.currentThread(); 80 } 81 82 protected synchronized boolean startRead() { 83 Thread t = Thread.currentThread(); 84 Object c = readers_.get(t); 85 if (c != null) { // already held -- just increment hold count 86 readers_.put(t, new Integer(((Integer)(c)).intValue()+1)); 87 ++activeReaders_; 88 return true; 89 } 90 else if (allowReader()) { 91 readers_.put(t, IONE); 92 ++activeReaders_; 93 return true; 94 } 95 else 96 return false; 97 } 98 99 protected synchronized boolean startWrite() { 100 if (activeWriter_ == Thread.currentThread()) { // already held; re-acquire 101 ++writeHolds_; 102 return true; 103 } 104 else if (writeHolds_ == 0) { 105 if (activeReaders_ == 0 || 106 (readers_.size() == 1 && 107 readers_.get(Thread.currentThread()) != null)) { 108 activeWriter_ = Thread.currentThread(); 109 writeHolds_ = 1; 110 return true; 111 } 112 else 113 return false; 114 } 115 else 116 return false; 117 } 118 119 120 protected synchronized Signaller endRead() { 121 Thread t = Thread.currentThread(); 122 Object c = readers_.get(t); 123 if (c == null) 124 throw new IllegalStateException(); 125 --activeReaders_; 126 if (c != IONE) { // more than one hold; decrement count 127 int h = ((Integer)(c)).intValue()-1; 128 Integer ih = (h == 1)? IONE : new Integer(h); 129 readers_.put(t, ih); 130 return null; 131 } 132 else { 133 readers_.remove(t); 134 135 if (writeHolds_ > 0) // a write lock is still held by current thread 136 return null; 137 else if (activeReaders_ == 0 && waitingWriters_ > 0) 138 return writerLock_; 139 else 140 return null; 141 } 142 } 143 144 protected synchronized Signaller endWrite() { 145 --writeHolds_; 146 if (writeHolds_ > 0) // still being held 147 return null; 148 else { 149 activeWriter_ = null; 150 if (waitingReaders_ > 0 && allowReader()) 151 return readerLock_; 152 else if (waitingWriters_ > 0) 153 return writerLock_; 154 else 155 return null; 156 } 157 } 158 159 } 160 161 |
|||
Java API By Example, From Geeks To Geeks. |
Conditions of Use |
About Us
© 2002 - 2005, KickJava.com, or its affiliates
|