Mega Code Archive

 
Categories / Java / Threads
 

Read Write Lock

/*  * Copyright 2002 (C) TJDO.  * All rights reserved.  *  * This software is distributed under the terms of the TJDO License version 1.0.  * See the terms of the TJDO License in the documentation provided with this software.  *  * $Id: ReadWriteLock.java,v 1.5 2006/08/02 22:41:25 jackknifebarber Exp $  */ /**  * A simple read-write lock implementation.  Multiple threads may lock using  * readLock(), only one can lock using writeLock().  The caller is responsible  * for coding a try-finally that ensures unlock() is called for every readLock()  * and writeLock() call.  *  * <p>A ReadWriteLock is recursive; with one exception, a thread can re-lock an  * object it already has locked.   Multiple read locks can be acquired by the  * same thread, as can multiple write locks.  The exception however is that a  * write lock cannot be acquired when a read lock is already held (to allow  * this would cause deadlocks).  *  * <p>Successive lock calls from the same thread must be matched by an  * equal number of unlock() calls.  *  * @author <a href="mailto:mmartin5@austin.rr.com">Mike Martin</a>  * @version $Revision: 1.5 $  */ public class ReadWriteLock {     private static final int WAIT_LOG_INTERVAL = 5000;     /** A count for each thread indicating the number of read locks it holds. */     private ThreadLocal readLocksByThread;     /** The number of read locks held across all threads. */     private int readLocks;     /** The number of write locks held (by writeLockedBy). */     private int writeLocks;     /** The thread holding the write lock(s), if any. */     private Thread writeLockedBy;     /**      * An object holding a per-thread read-lock count.      */     private static class Count     {         public int value = 0;     }     /**      * Constructs read-write lock.      */     public ReadWriteLock()     {         readLocksByThread = new ThreadLocal()             {                 public Object initialValue()                 {                     return new Count();                 }             };         readLocks      = 0;         writeLocks     = 0;         writeLockedBy  = null;     }     /**      * Acquire a read lock.  The calling thread will be suspended until no other      * thread holds a write lock.      *      * <p>If the calling thread already owns a write lock for the object a read      * lock is immediately acquired.      *      * @exception InterruptedException      *      If the thread is interrupted while attempting to acquire the lock.      */     public synchronized void readLock() throws InterruptedException     {         Thread me = Thread.currentThread();         Count myReadLocks = (Count)readLocksByThread.get();         if (writeLockedBy != me)         {             while (writeLocks > 0)             {                 wait(WAIT_LOG_INTERVAL);                 if (writeLocks > 0)                     System.out.println("Still waiting for read lock on ");             }         }         ++readLocks;         ++myReadLocks.value;     }     /**      * Acquire a write lock.  The calling thread will be suspended until no      * other thread holds a read or write lock.      *      * <p>This method cannot be called if the thread already owns a read lock on      * the same ReadWriteLock object, otherwise an      * <code>IllegalStateException</code> is thrown.      *      * @exception IllegalStateException      *      If the thread already holds a read lock on the same object.      * @exception InterruptedException      *      If the thread is interrupted while attempting to acquire the lock.      */     public synchronized void writeLock() throws InterruptedException     {         Thread me = Thread.currentThread();         Count myReadLocks = (Count)readLocksByThread.get();         if (myReadLocks.value > 0)             throw new IllegalStateException("Thread already holds a read lock");         if (writeLockedBy != me)         {             while (writeLocks > 0 || readLocks > 0)             {                 wait(WAIT_LOG_INTERVAL);                 if (writeLocks > 0 || readLocks > 0)                     System.out.println("Still waiting for write lock on ");             }             writeLockedBy = me;         }         ++writeLocks;     }     /**      * Release a read or write lock.  Must be called in a finally block after      * acquiring a lock.      */     public synchronized void unlock()     {         Thread me = Thread.currentThread();         Count myReadLocks = (Count)readLocksByThread.get();         if (myReadLocks.value > 0)         {             --myReadLocks.value;             --readLocks;         }         else if (writeLockedBy == me)         {             if (writeLocks > 0)             {                 if (--writeLocks == 0)                     writeLockedBy = null;             }         }         notifyAll();     }     public String toString()     {         StringBuffer s = new StringBuffer(super.toString());         s.append(": readLocks = ").append(readLocks)          .append(", writeLocks = ").append(writeLocks)          .append(", writeLockedBy = ").append(writeLockedBy);         return s.toString();     } }