import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
class IdeOne {
private static final Semaphore lock
= new Semaphore
(Integer.
MAX_VALUE,
true);
lock.acquire();
try {
// Do some read locked stuff
System.
out.
println("READ LOCK"); latch.countDown();
latch.await();
} finally {
lock.release();
System.
out.
println("RELEASE READ"); }
}
try {
System.
out.
println("WRITE LOCK"); latch.countDown();
latch.await();
// Do write locked stuff
} finally {
System.
out.
println("RELEASE WRITE"); }
}
final ExecutorService executorService = Executors.newFixedThreadPool(5);
final CountDownLatch latch = new CountDownLatch(3);
executorService.submit(() -> {
try {
doReadLocked(latch);
e.printStackTrace();
}
});
executorService.submit(() -> {
try {
doReadLocked(latch);
e.printStackTrace();
}
});
// At this point there are 2 readers, so the write lock will be queued.
final CountDownLatch writeLatch = new CountDownLatch(2);
executorService.submit(() -> {
try {
doWriteLocked(writeLatch);
e.printStackTrace();
}
});
System.
out.
println("(2) WRITE COUNT = " + writeLatch.
getCount());
// Give time to ensure that the write has been submitted.
TimeUnit.SECONDS.sleep(1L);
final CountDownLatch finalReadLatch = new CountDownLatch(1);
// Before releasing the write, submit another read lock.
executorService.submit(() -> {
try {
System.
out.
println("Submitting READ"); doReadLocked(finalReadLatch);
e.printStackTrace();
}
});
TimeUnit.SECONDS.sleep(1L);
System.
out.
println("(1) READ COUNT = " + finalReadLatch.
getCount());
// Free up all the first ones queued.
latch.countDown();
// Give write lock time to start...
TimeUnit.SECONDS.sleep(1L);
System.
out.
println("(1) WRITE COUNT = " + writeLatch.
getCount()); System.
out.
println("(1) READ COUNT = " + finalReadLatch.
getCount());
// Release the writer and give final reader time to start up...
writeLatch.countDown();
TimeUnit.SECONDS.sleep(1L);
System.
out.
println("(0) READ COUNT = " + finalReadLatch.
getCount());
executorService.shutdown();
TimeUnit.SECONDS.sleep(1L);
}
}