Last active
December 9, 2018 12:07
-
-
Save asm0dey/cb560535a8ab0ae26b20 to your computer and use it in GitHub Desktop.
naive ReadWriteLock realization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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