Skip to content

Instantly share code, notes, and snippets.

@asm0dey
Last active December 9, 2018 12:07
Show Gist options
  • Save asm0dey/cb560535a8ab0ae26b20 to your computer and use it in GitHub Desktop.
Save asm0dey/cb560535a8ab0ae26b20 to your computer and use it in GitHub Desktop.
naive ReadWriteLock realization
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author finkel
*/
public class JavaApplication1 {
private static final RWLock rWLock = new RWLock();
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(8);
newFixedThreadPool.submit(lock(true, 10000, "read"));
newFixedThreadPool.submit(lock(true, 7000, "read2"));
newFixedThreadPool.submit(lock(false, 9000, "write"));
newFixedThreadPool.submit(lock(false, 7000, "write2"));
newFixedThreadPool.submit(lock(true, 5000, "read3"));
newFixedThreadPool.submit(() -> {
System.out.println("Unlocking other thread");
try {
rWLock.unlockRead();
} catch (Exception ex) {
Logger.getLogger(JavaApplication1.class.getName()).log(Level.SEVERE, null, ex);
}
});
newFixedThreadPool.shutdown();
}
private static Runnable lock(final boolean read, final int time, final String name) {
return () -> {
if (read) {
rWLock.lockRead();
} else {
rWLock.lockWrite();
}
try {
System.out.println(name + "Start");
Thread.sleep(time);
System.out.println(name + "Finish");
} catch (InterruptedException ex) {
Logger.getLogger(JavaApplication1.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (read) {
rWLock.unlockRead();
} else {
rWLock.unlockWrite();
}
} catch (Exception ex) {
Logger.getLogger(JavaApplication1.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
}
}
import java.util.function.Supplier;
public class RWLock {
private final ReadLock readLock = new ReadLock(this);
private final WriteLock writeLock = new WriteLock(this);
final Object globalLock = new Object();
public void lockRead() {
readLock.lock();
}
public void unlockRead() throws Exception {
readLock.unlock();
}
public void lockWrite() {
writeLock.lock();
}
public void unlockWrite() throws Exception {
writeLock.unlock();
}
private static class AbstractLock {
protected final RWLock rwLock;
protected volatile long count = 0;
protected ThreadLocal<Boolean> isLocked = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return false;
}
};
public AbstractLock(RWLock rwLock) {
this.rwLock = rwLock;
}
boolean isLocked() {
return count > 0;
}
void unlock() throws Exception {
if (isLocked.get()) {
synchronized (rwLock.globalLock) {
count--;
isLocked.set(false);
rwLock.globalLock.notifyAll();
}
} else {
throw new Exception("Can't unlock from this thread");
}
}
protected void internalLock(Supplier<Boolean> s) {
synchronized (rwLock.globalLock) {
while (s.get()) {
try {
rwLock.globalLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++;
isLocked.set(true);
}
}
}
private static class ReadLock extends AbstractLock {
private ReadLock(RWLock rwLock) {
super(rwLock);
}
void lock() {
internalLock(rwLock.writeLock::isLocked);
}
}
private static class WriteLock extends AbstractLock {
public WriteLock(RWLock rwLock) {
super(rwLock);
}
void lock() {
internalLock(() -> count > 0 || rwLock.readLock.isLocked());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment