javamultithreadingconcurrencysemaphorereaderwriterlock

Why doesnt my ReaderWriter solution work ? (java, concurrency)


So lately i ve been trying to wrap my head around concurrency. And currently I m trying to find a solution for the ReaderWriter Problem.

I got a class File, it counts the number of Readers/Writers and has two Semaphores.

When a Reader tries to read it has to wait as long as there is a Writer Thread writing. When it enters readCount gets incremented within the readerSemaphore & decremented within the same Semaphore when it leaves.

When a Writer tries to enter it has to wait for as long as there is more than one reader. When it enters it aquires the writerSemaphore and increaese the writerCount. When it leaves it releases the Semaphore.

For some reason that I cant figure out the Writers are not editing the String file in class File.

Thanks in advance :)

public class Main { 
public static void main(String[]args) {

    File file = new File("1. Chapter: ");

    Writer w1 = new Writer(file, " w1 ");
    Writer w2 = new Writer(file, " w2 ");

    Reader r1 = new Reader(file);
    Reader r2 = new Reader(file);
    Reader r3 = new Reader(file);
    Reader r4 = new Reader(file);
    Reader r5 = new Reader(file);

    w1.start();
    w2.start();

    r1.start();
    r2.start();
    r3.start();
    r4.start();
    r5.start();     

    try {
        w2.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    System.out.println("-> Final output: " + file.file);
}}


public class File { 
public String file;

private int readCount;
private int writeCount;

private Semaphore semReader;
private Semaphore semWriter;

public File(String file) {
    this.file = file;

    readCount = 0;
    writeCount = 0;

    semReader = new Semaphore(1);
    semWriter = new Semaphore(1);
}

public synchronized void startReading() {

    try {

        while(writeCount == 1) {
            Thread.currentThread().wait();
        }

        semReader.acquire();
        readCount++;
        semReader.release();

        System.out.println(" --- File was read");

    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public synchronized String endReading() {

    String temp = file;

    try {   

        semReader.acquire();    
        readCount--;    
        semReader.release();

    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    return temp;
}

public synchronized void startWriting(String edit) {

    try {

        while(readCount > 0) {
            Thread.currentThread().wait();
        }

        semWriter.acquire();
        writeCount++;   

        System.out.println(" --- File got edited");
        file = file + "hi";
    }
    catch (Exception e) {
    }   
}

public synchronized void endWriting() {

    writeCount--;
    semWriter.release();
}}




public class Writer extends Thread { 
private File file;
private String edit;

public Writer(File file, String edit) {
    this.file = file;
    this.edit = edit;
}

@Override
public void run() {

    Random rand = new Random();

    try {

        sleep(1000);
        System.out.println(">W: " + Thread.currentThread().getName() + " started first write.");
        file.startWriting(" first" + edit);

        sleep(3000);
        System.out.println(">W: " + Thread.currentThread().getName() + " ended first write.");
        file.endWriting();

        sleep(2000);
        System.out.println(">W: " + Thread.currentThread().getName() + " started second write.");
        file.startWriting(" second" + edit);

        sleep(3000);
        System.out.println(">W: " + Thread.currentThread().getName() + " ended second write.");
        file.endWriting();

        System.out.println(">W: " + Thread.currentThread().getName() + " finished");

    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}}




public class Reader extends Thread { 
private File file;

public Reader(File file) {
    this.file = file;
}

@Override
public void run() {

    Random rand = new Random();

    try {

        sleep(rand.nextInt(2000));
        System.out.println(">R: " + Thread.currentThread().getName() + " startet first read.");
        file.startReading();

        sleep(3000);
        System.out.print(">R: " + Thread.currentThread().getName() + " ended first read: ");
        System.out.println(file.endReading());

        sleep(rand.nextInt(2000));
        System.out.println(">R: " + Thread.currentThread().getName() + " startet second read.");            
        file.startReading();

        sleep(3000);
        System.out.print(">R: " + Thread.currentThread().getName() + " ended second read: ");   
        System.out.println(file.endReading());

        System.out.println(">R: " + Thread.currentThread().getName() + " finished");

    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}}

Solution

  • Edit:

    Thread.currentThread().wait() was wrong. Waiting on threads is discouraged in the java docs.

    Thanks, @JB Nizet for helping me.