Skip to content

Instantly share code, notes, and snippets.

@pratapaditya1997
Created July 8, 2020 16:30
Show Gist options
  • Save pratapaditya1997/2174e47d2ec96ab2db9c083b911b07c4 to your computer and use it in GitHub Desktop.
Save pratapaditya1997/2174e47d2ec96ab2db9c083b911b07c4 to your computer and use it in GitHub Desktop.
Lock and ReadWriteLock implementation
/*
* in ReadWriteLock notifyAll() is called rather than notify()
* inside this lock many threads are waiting for read access and threads waiting for write access. if a thread is awakened by notify() was a read access thread, it would be put back to waiting because there are threads waiting for write access.
* however none of the threads awaiting write access are awakened, so nothing more happens. no threads gain neither read nor write access.
*/
class ReadWriteLock {
private int readers = 0;
private int writers = 0;
private int writeRequests = 0;
public synchronized void lockRead() {
while(writers > 0 || writeRequests > 0) {
wait();
}
readers++;
}
public synchronized void unlockRead() {
readers--;
notifyAll();
}
public synchronized void lockWrite() {
writeRequests++;
while(readers > 0 || writers > 0) {
wait();
}
writeRequests--;
writers++;
}
public synchronized void unlockWrite() {
writers--;
notifyAll();
}
}
class ReadWriteLockReentrant {
private Map<Thread, Integer> readingThreads = new HashMap<Thread, Integer>();
private int writerAccesses = 0;
private int writeRequests = 0;
private Thread writingThread = null;
public synchronized void lockRead() {
Thread callingThread = Thread.currentThread();
while(!canGrantReadAccess(callingThread)) {
wait();
}
readingThreads.put(callingThread, getAccessCount(callingThread) + 1);
}
public synchronized void unlockRead() {
Thread callingThread = Thread.currentThread();
int accessCount = getAccessCount(callingThread);
if(accessCount == 1) {
readingThreads.remove(callingThread);
} else {
readingThreads.put(callingThread, accessCount - 1);
}
notifyAll();
}
public synchronized void lockWrite() {
writeRequests++;
Thread callingThread = Thread.currentThread();
while(!canGrantWriteAccess(callingThread)) {
wait();
}
writeRequests--;
writerAccesses++;
writingThread = callingThread;
}
public synchronized void unlockWrite() {
writerAccesses--;
if(writerAccesses == 0) {
writingThread = null;
}
notifyAll();
}
private boolean canGrantReadAccess(Thread callingThread) {
if(writers > 0) return false;
if(isReader(callingThread)) return true;
if(writeRequests > 0) return false;
return true;
}
private boolean canGrantWriteAccess(Thread callingThread) {
if(hasReaders()) return false;
if(writingThread == null) return true;
if(!isWriter(callingThread)) return false;
return true;
}
private int getAccessCount(Thread callingThread) {
Integer accessCount = readingThreads.get(callingThread);
if(accessCount == null) return 0;
return accessCount.intValue();
}
private boolean hasReaders() {
return readingThreads.size() > 0;
}
private boolean isReader(Thread callingThread) {
return readingThreads.get(callingThread) != null;
}
private boolean isWriter(Thread callingThread) {
return writingThread == callingThread;
}
}
// to make the Lock class re-entrant we need to store current thread too
class Lock {
boolean isLocked = false;
Thread lockedBy = null;
int lockedCount = 0;
public synchronized void lock() {
Thread callingThread = Thread.currentThread();
while(isLocked && lockedBy != callingThread) {
wait();
}
isLocked = true;
lockedCount++;
lockedBy = currentThread;
}
public synchronized void unlock() {
Thread currentThread = Thread.currentThread();
if(this.lockedBy == currentThread) {
lockedCount--;
if(lockedCount == 0) {
isLocked = false;
notify();
}
}
}
}
// we should always call unlock() method from the finally block so that other threads can block it if there is some exception
class Counter {
private Lock lock = new Lock();
private int count = 0;
public int inc() {
lock.lock();
try {
int newCount = ++count;
} finally {
lock.unlock();
}
return newCount;
}
}
public class Locking {
public static void main(String[] args) {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment