Lock & Condition

Difference between intrinsic (synch, wait(), notify()) and explicit locking (using lock, semaphores):

  • explicit locks provide interruptability, timeouts, fairness.

Reentrant lock: when a thread holds a lock, it can enter a block synchronized on the lock it is holding.

Calling unlock() from a finally clause.

lock.lock();
try{
    //do something in critical region which may throw Exception
} finally {
    lock.unlock();
}

Lock Reentrance

We need to count the number of times the lock has been locked by the same thread. Otherwise, a single call tounlock()will unlock the lock, even if the lock has been locked multiple times.

public class Lock{

  boolean isLocked = false;
  Thread  lockedBy = null;
  int     lockedCount = 0;

  public synchronized void lock()
  throws InterruptedException{
    Thread callingThread = Thread.currentThread();
    while(isLocked && lockedBy != callingThread){
      wait();
    }
    isLocked = true;
    lockedCount++;
    lockedBy = callingThread;
  }


  public synchronized void unlock(){
    if(Thread.curentThread() == this.lockedBy){
      lockedCount--;

      if(lockedCount == 0){
        isLocked = false;
        notify();
      }
    }
  }

  ...
}

ReadWrite Lock

http://tutorials.jenkov.com/java-concurrency/read-write-locks.html

ReadWriteLock in java concurrent library

private ReadWriteLock lock = new ReentrantReadWriteLock(true);
private Lock readLock = lock.readLock();
private Lock writeLock = lock.writeLock();

public String put(Long key, String value) {
    writeLock.lock();
    try {
        return cache.put(key, value);
    } finally {
        writeLock.unlock();
    }
}

public String get(Long key) {
    readLock.lock();
    try {
        return cache.get(key);
    } finally {
        readLock.unlock();
    }
}

Semaphore

Possible implementation:

public class BoundedSemaphore {
  private int signals = 0;
  private int bound   = 0;

  public BoundedSemaphore(int upperBound){
    this.bound = upperBound;
  }

  public synchronized void take() throws InterruptedException{
    while(this.signals == bound) wait();
    this.signals++;
    this.notify();
  }

  public synchronized void release() throws InterruptedException{
    while(this.signals == 0) wait();
    this.signals--;
    this.notify();
  }
}

It is possible to use a bounded semaphore as a lock to limit the number of threads allowed into a section of code.

Semaphore semaphore = new Semaphore(5);
try {
    //semaphore.acquire();
    if(semaphore.tryAcquire()) {
        //guarded block of code
    } else {

    }
} finally {
    semaphore.release();
}

Condition

  • Condition factors out the Object monitor methods (wait, notify and notifyAll) into distinct objects to give the effect of having multiple wait-sets per object.
  • Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods.
  • Because access to this shared state information occurs in different threads, it must be protected, so a lock of some form is associated with the condition.
final Lock lock = new ReentrantLock();
final Condition notFull  = lock.newCondition(); 
final Condition notEmpty = lock.newCondition();

results matching ""

    No results matching ""