syncronized readers and writers in java - java

i want to implement my own readWriteLock class, without using the readWriteLock provided by the API.
i have this situation:
public void read(){
if(!write){
read = true;
//any thread can enter here and read;
....
read = false;
}
}
public syncrhonized void write(){
if(!read){
write = true;
//only one thread at time can write.
....
write = false;
}
}
there are a lot of bad situations which can happen with this code, for example:
if one thread enter inside if(!read){...} and immediately this become true so it can't write.
if threads enter inside if(!write){...} and immediately this become true so they can't read.
i manage to use atomicBoolean, but this is a mutex - exclusion for all threads that at the same time want to read and this doesn't resolve the ambiguity.
can someone provide me an explanation?
thanks in advance.

What you are trying to do is not a good idea. As you have already mentioned yourself, there is already an existing mechanism for that. Why reinventing the wheel?
If your really need your own implementation, to do it correctly many more synchronized blocks are needed. You need to synchronize getting and releasing read lock, you cannot only synchronize access to write method.
Example which I have not checked but looks fine. All credits to Jakob Jenkov (http://tutorials.jenkov.com/java-concurrency/read-write-locks.html)
public class ReadWriteLock{
private int readers = 0;
private int writers = 0;
private int writeRequests = 0;
public synchronized void lockRead() throws InterruptedException{
while(writers > 0 || writeRequests > 0){
wait();
}
readers++;
}
public synchronized void unlockRead(){
readers--;
notifyAll();
}
public synchronized void lockWrite() throws InterruptedException{
writeRequests++;
while(readers > 0 || writers > 0){
wait();
}
writeRequests--;
writers++;
}
public synchronized void unlockWrite() throws InterruptedException{
writers--;
notifyAll();
}
}

Related

java multiple writers and multiple readers locks

I'm trying to implement a system that follows the following constraints :
I have a shared resource, for example Atomic array
I want to support multiple reads from the array simultaneously.
I want to support multiple writes to the array simultaneously
I dont want read and write operations to happen simultaneously.
I found [this][1] stackoverflow post regarding a similar goal but I think that the solution suggested there is allowing reads simultaneously to writes :
Class ReadAndWrite {
private ReentrantLock readLock;
private ReentrantLock writeLock;
private AtomicInteger readers;
private AtomicInteger writers;
private File file;
public void write() {
if (!writeLock.isLocked()) {
readLock.tryLock();
writers.incrementAndGet(); // Increment the number of current writers
// ***** Write your stuff *****
writers.decrementAndGet(); // Decrement the number of current writers
if (readLock.isHeldByCurrentThread()) {
while(writers != 0); // Wait until all writers are finished to release the lock
readLock.unlock();
}
} else {
writeLock.lock();
write();
}
}
public void read() {
if (!readLock.isLocked()) {
writeLock.tryLock();
readers.incrementAndGet();
// ***** read your stuff *****
readers.decrementAndGet(); // Decrement the number of current read
if (writeLock.isHeldByCurrentThread()) {
while(readers != 0); // Wait until all writers are finished to release the lock
writeLock.unlock();
}
} else {
readLock.lock();
read();
}
}
As I see it, this code allows reads and writes simultaneously, for example : two threads will try to read/writer at the same time. Each one of them will enter the first if in the write/read. How can I make sure that the writes blocks the reads and reads blocks writes ?
[1]: Multiple readers and multiple writers(i mean multiple) synchronization
Rather than checking the lock repeatedly, just attempt using it:
private void writeInternal() {
//thread-unsafe writing code
}
public void write() {
if (!writeLock.tryLock()) {
writeLock.lock();
}
try {
this.writeInternal(); //in try-block to ensure unlock is called
} finally {
writeLock.unlock();
}
}
Using the readLock would be a similar approach. You also want to ensure you're truly using Read/Write locks and not just two separate locks:
private final ReadWriteLock lock;
public ReadAndWrite() {
this.lock = new ReentrantReadWriteLock();
}
Then you would access read/write locks via this.lock.readLock(), etc.

In the context of monitors, where does a blocked thread continue executing after being woken by a call to notify()?

Does it continue executing immediately after where it called wait()? Does it start all the way from the beginning of the service method?
A passage from Stephen Hartley's Concurrent Programming: The Java Programming Language had this to say about the matter, which I'm not sure if I understand entirely:
It is not possible with this notification scheme to wait in the middle of a synchronized monitor service method for a signal and then continue executing inside the monitor service method at that point after receiving the signal.
The notification scheme it is referring to is an implementation of the solution to the Readers and Writers problem using notification objects.
Here is a snippet of code of that solution (I'm only showing methods related to Readers):
private int numReaders = 0;
private boolean isWriting = false;
private Vector waitingReaders = new Vector();
private Vector waitingWriters = new Vector();
public void startRead(int i) {
Object convey = new Object();
synchronized (convey) {
if (cannotReadNow(convey))
try { convey.wait(); }
catch (InterruptedException e) {}
}
}
private synchronized boolean cannotReadNow(Object convey) {
boolean status;
if (isWriting || waitingWriters.size() > 0) {
waitingReaders.addElement(convey); status = true;
} else {
numReaders++; status = false;
}
return status;
}
public synchronized void endRead(int i) {
numReaders--;
if (numReaders == 0 && waitingWriters.size() > 0) {
synchronized (waitingWriters.elementAt(0)) {
waitingWriters.elementAt(0).notify();
}
waitingWriters.removeElementAt(0);
isWriting = true;
}
}
The reason I'm so confused is the quote above seems to contradict programming practices shown in code samples from the same book.
For example, this is a snippet of code of the Readers and Writers solution using plain monitors, without notification objects
public synchronized void startRead(int i) {
long readerArrivalTime = 0;
if (numWaitingWriters > 0 || numWriters > 0) {
numWaitingWriters++;
readerArrivalTime = age();
while (readerArrivalTime >= startWritingReadersTime)
try {wait();}
catch (InterruptedException e) {}
numWaitingReaders--;
}
numReaders++;
}
If it's not possible for a thread to continue executing where it was blocked by a call to wait(), why is a while-loop used to check for the condition? If every thread that gets blocked and then regains entry to the monitor via a call to startRead() has to begin from the beginning of that method, as the quote above seems to be suggesting, wouldn't an if-statement suffice for checking the condition?
Moreover, how does any of this explain this next quote, which in the book follows immediately after the quote above:
To avoid deadlock, the thread must leave the synchronized method with a return statement before waiting inside the notification object.
If I understood this question... Try this:
public synchronized void startRead(int i) {
long readerArrivalTime = 0;
if (numWaitingWriters > 0 || numWriters > 0) {
numWaitingWriters++;
readerArrivalTime = age();
while (readerArrivalTime >= startWritingReadersTime)
try {wait();}
catch (InterruptedException e) {}
numWaitingReaders--;
}
numReaders++;
}
public synchronized void endRead(int i) {
numReaders--;
if (numReaders == 0 && waitingWriters.size() > 0) {
notify();
waitingWriters.removeElementAt(0);
isWriting = true;
}
}
concreteObject.wait/notify/notifyAll methods can be called only from synchronized(concreteObject) block. If you call their without concreteObject (just wait() or notify()), it's same as this.wait() or this.notify().
Synchronized non static methods are same as synchronized(this) blocks.

Are unsynchronized reads (combined with synchronized writes) eventually consistent

I have a use case with many writer threads and a single reader thread. The data being written is an event counter which is being read by a display thread.
The counter only ever increases and the display is intended for humans, so the exact point-in-time value is not critical. For this purpose, I would consider a solution to be correct as long as:
The value seen by the reader thread never decreases.
Reads are eventually consistent. After a certain amount of time without any writes, all reads will return the exact value.
Assuming writers are properly synchronized with each other, is it necessary to synchronize the reader thread with the writers in order to guarantee correctness, as defined above?
A simplified example. Would this be correct, as defined above?
public class Eventual {
private static class Counter {
private int count = 0;
private Lock writeLock = new ReentrantLock();
// Unsynchronized reads
public int getCount() {
return count;
}
// Synchronized writes
public void increment() {
writeLock.lock();
try {
count++;
} finally {
writeLock.unlock();
}
}
}
public static void main(String[] args) {
List<Thread> contentiousThreads = new ArrayList<>();
final Counter sharedCounter = new Counter();
// 5 synchronized writer threads
for(int i = 0; i < 5; ++i) {
contentiousThreads.add(new Thread(new Runnable(){
#Override
public void run() {
for(int i = 0; i < 20_000; ++i) {
sharedCounter.increment();
safeSleep(1);
}
}
}));
}
// 1 unsynchronized reader thread
contentiousThreads.add(new Thread(new Runnable(){
#Override
public void run() {
for(int i = 0; i < 30; ++i) {
// This value should:
// +Never decrease
// +Reach 100,000 if we are eventually consistent.
System.out.println("Count: " + sharedCounter.getCount());
safeSleep(1000);
}
}
}));
contentiousThreads.stream().forEach(t -> t.start());
// Just cleaning up...
// For the question, assume readers/writers run indefinitely
try {
for(Thread t : contentiousThreads) {
t.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static void safeSleep(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
//Don't care about error handling for now.
}
}
}
There is no guarantee that the readers would ever see an update to the count. A simple fix is to make count volatile.
As noted in another answer, in your current example, the "Final Count" will be correct because the main thread is joining the writer threads (thus establishing a happens-before relationship). however, your reader thread is never guaranteed to see any update to the count.
JTahlborn is correct, +1 from me. I was rushing and misread the question, I was assuming wrongly that the reader thread was the main thread.
The main thread can display the final count correctly due to the happens-before relationship:
All actions in a thread happen-before any other thread successfully returns from a join on that thread.
Once the main thread has joined to all the writers then the counter's updated value is visible. However, there is no happens-before relationship forcing the reader's view to get updated, you are at the mercy of the JVM implementation. There is no promise in the JLS about values getting visible if enough time passes, it is left open to the implementation. The counter value could get cached and the reader could possibly not see any updates whatsoever.
Testing this on one platform gives no assurance of what other platforms will do, so don't think this is OK just because the test passes on your PC. How many of us develop on the same platform we deploy to?
Using volatile on the counter or using AtomicInteger would be good fixes. Using AtomicInteger would allow removing the locks from the writer thread. Using volatile without locking would be OK only in a case where there is just one writer, when two or more writers are present then ++ or += not being threadsafe will be an issue. Using an Atomic class is a better choice.
(Btw eating the InterruptedException isn't "safe", it just makes the thread unresponsive to interruption, which happens when your program asks the thread to finish early.)

Implementing a cyclicbarrier in java using semaphores

The question is as follows, since the barrier is only called using down() so that it would wait for the n threads to arrive and then execute all n threads together in the critical region now how do I inform the threads calling on barrier.down that it can move on now. I tried adding notifyAll() after phase2() and that doesn't work. Help? :)
public class cyclicBarrier {
private int n;
private int count;
private semaphore mutex;
private semaphore turnstile;
private semaphore turnstile2;
public cyclicBarrier(int n){
this.n = n;
this.count = 0;
this.mutex = new semaphore(1);
this.turnstile = new semaphore(0);
this.turnstile2 = new semaphore(0);
}
public synchronized void down() throws InterruptedException{
this.phase1(); //waits for n threads to arrive
this.phase2(); //waits for n threads to execute
}
private synchronized void phase1() throws InterruptedException {
this.mutex.down();
this.count++;
if(this.count == this.n){
for(int i = 0; i < this.n; i++){
this.turnstile.signal(); //when n threads received then move on to phase 2
}
}
this.mutex.signal();
this.turnstile.down(); //keeps waiting till I get n threads
}
private synchronized void phase2() throws InterruptedException {
this.mutex.down();
this.count--;
if(this.count == 0){
for(int i = 0; i < this.n; i++){
this.turnstile2.signal(); //reset the barrier for reuse
}
}
this.mutex.signal();
this.turnstile2.down(); //keeps waiting till n threads get executed
}
}
public class semaphore {
private int counter;
public semaphore(int number){
if (number > 0) {
this.counter = number;
}
}
public synchronized void signal(){
this.counter++;
notifyAll();
}
public synchronized void down() throws InterruptedException{
while (this.counter <= 0){
wait();
}
this.counter--;
}
}
I see you're using the solution from The Little Book of Semaphores. One main point of the book is that you can solve many coordination problems using semaphores as the only coordination primitive. It is perfectly fine to use synchronized to implement a semaphore, since that is necessary to do it correctly. It misses the point, however, to use synchronized in the methods which solve a puzzle that is supposed to be solved with semaphores.
Also, I think it doesn't work in your case: don't you get a deadlock at this.turnstile.down()? You block on a semaphore which holding an exclusive lock (through synchronized) on the object and method which would allow that semaphore to get released.
Addressing the question as stated: you signal to threads that they can proceed by returning from barrier.down(). You ensure that you don't return too soon by doing turnstile.down().
Aside: Semaphore implementation
Your semaphore implementation looks correct, except that you only allow non-negative initial values, which is at least non-standard. Is there some motivation for doing this that I can't see? If you think negative initial values are wrong, why not throw an error instead of silently doing something else?
Aside: Other synchronization primitives
Note that the java constructs synchronized, .wait() and .notify() correspond to the Monitor coordination primitive. It may be instructive to solve the puzzles with monitors (or other coordination primitives) instead of semaphores, but I would recommend keeping those efforts separate. I've had a bit of fun trying to solve a puzzle using Haskell's Software Transactional Memory.
Aside: On runnability
You say you have tried things, which indicates that you have some code that allows you to run the code in the question. It would have been helpful if you had included that code, so we could easily run it too. I probably would have checked that my hypothesized deadlock actually occurs.

Thread Mutual Exclusive Section

Hello I just had phone interview I was not able to answer this question and would like to know the answer, I believe, its advisable to reach out for answers that you don't know. Please encourage me to understand the concept.
His question was:
"The synchronized block only allows one thread a time into the mutual exclusive section.
When a thread exits the synchronized block, the synchronized block does not specify
which of the waiting threads will be allowed next into the mutual exclusive section?
Using synchronized and methods available in Object, can you implement first-come,
first-serve mutual exclusive section? One that guarantees that threads are let into
the mutual exclusive section in the order of arrival? "
public class Test {
public static final Object obj = new Object();
public void doSomething() {
synchronized (obj) {
// mutual exclusive section
}
}
}
Here's a simple example:
public class FairLock {
private int _nextNumber;
private int _curNumber;
public synchronized void lock() throws InterruptedException {
int myNumber = _nextNumber++;
while(myNumber != _curNumber) {
wait();
}
}
public synchronized void unlock() {
_curNumber++;
notifyAll();
}
}
you would use it like:
public class Example {
private final FairLock _lock = new FairLock();
public void doSomething() {
_lock.lock();
try {
// do something mutually exclusive here ...
} finally {
_lock.unlock();
}
}
}
(note, this does not handle the situation where a caller to lock() receives an interrupted exception!)
what they were asking is a fair mutex
create a FIFO queue of lock objects that are pushed on it by threads waiting for the lock and then wait on it (all this except the waiting in a synchronized block on a separate lock)
then when the lock is released an object is popped of the queue and the thread waiting on it woken (also synchronized on the same lock for adding the objects)
You can use ReentrantLock with fairness parameter set to true. Then the next thread served will be the thread waiting for the longest time i.e. the one that arrived first.
Here is my attempt. The idea to give a ticket number for each thread. Threads are entered based on the order of their ticket numbers. I am not familiar with Java, so please read my comments:
public class Test {
public static final Object obj = new Object();
unsigned int count = 0; // unsigned global int
unsigned int next = 0; // unsigned global int
public void doSomething() {
unsigned int my_number; // my ticket number
// the critical section is small. Just pick your ticket number. Guarantee FIFO
synchronized (obj) { my_number = count ++; }
// busy waiting
while (next != my_number);
// mutual exclusion
next++; // only one thread will modify this global variable
}
}
The disadvantage of this answer is the busy waiting which will consume CPU time.
Using only Object's method and synchronized, in my point of view is a little difficult. Maybe, by setting each thread a priority, you can garantee an ordered access to the critical section.

Categories

Resources