javamultithreadingthread-sleepreaderwriterlock

Reader writers problem using Java Threads


I have been trying to implement the reader writer problem in Java. But when the Thread.Sleep(5000) is executed, the current thread process is not interrupted.

For example, when the first reader has entered the database, and the process sleeps for 5 seconds, I want the second reader to enter the database. But in my code, the second reader only enters the database after the first reader wakes up and leaves the database

How do I achieve my desired result?

import java.util.Scanner;

class CriticalSec {
    static boolean mutex = true;
    static boolean db = true;
    static int readerCount = 0;
    static Writer arrWriter = new Writer();
    static Reader1 r1= new Reader1();
    static Reader2 r2= new Reader2();

    public void readerEnter() throws InterruptedException {
        if (readerCount==0){
            r1.enter();
        }else{
            r1.enter();
        }
        if (mutex) {
            mutex = false;
        }
        readerCount += 1;
        if (readerCount == 1) {
            if (db) {
                db = false;
            } else {
                System.out.println("\nReader cannot enter database.\n");
                System.out.println("Waiting for writer to exit....");
                wait();
            }
        }
        if (!mutex) {
            mutex = true;
            Thread.sleep(5000);
            if (readerCount==1){
                r1.exit();
            }else{
                r2.exit();
            }
        }

    }

    public void WriterEnter() throws InterruptedException {
        arrWriter.enter();
        if (db) {
            db = false;
            Thread.sleep(5000);
            arrWriter.exit();
            notify();

        } else {
            System.out.println("Writer cannot enter database.");
            System.out.println("Waiting for writer/reader to exit....");
            wait();
        }

    }

}

class Reader1 extends Thread {
    public void run() {
        System.out.println("New reader created.");
    }

    public void enter() throws InterruptedException {
        System.out.println("\nReader 1 has entered in the database...\n");
    }

    public void exit() {
        if (CriticalSec.mutex) {
            CriticalSec.mutex = false;
        }
        CriticalSec.readerCount -= 1;
        if (CriticalSec.readerCount == 0) {
            CriticalSec.db = true;
        }
        CriticalSec.mutex = true;
        System.out.println("The reader 1 has now left");
    }
}

class Reader2 extends Thread {
    public void run() {
        System.out.println("New reader created.");
    }

    public void enter() throws InterruptedException {
        System.out.println("\nReader 2 has entered in the database...\n");
    }

    public void exit() {
        if (CriticalSec.mutex) {
            CriticalSec.mutex = false;
        }
        CriticalSec.readerCount -= 1;
        if (CriticalSec.readerCount == 0) {
            CriticalSec.db = true;
        }
        CriticalSec.mutex = true;
        System.out.println("The reader 1 has now left");
    }
}

class Writer extends Thread {
    public void run() {
        System.out.println("New Writer created.");
    }

    public void enter() throws InterruptedException {
        System.out.println("Writer has entered in the database.");
    }

    public void exit() {
        CriticalSec.db = false;
        System.out.println("Writer has left the database.");
    }
}

public class RWProblem {
    public static void main(String[] args) throws InterruptedException {
        Scanner sc = new Scanner(System.in);
        CriticalSec c = new CriticalSec();
        c.readerEnter();
        c.readerEnter();
        c.WriterEnter();
    }
}

I am just starting to learn Java, and I am sorry if my question is vague. I happy to provide more details.

Edit:

After brushing up on some important concepts and a lot of practice, I came up with a solution. Could someone please take a look at it and tell me if its alright? How can I improve it?

class RW {
    boolean dbOccupied = false;
    int readerCount = 0;
    boolean writer=false;

    public void readerEnter() throws InterruptedException {
        while (true) {
            synchronized (this) {
                while (dbOccupied && readerCount == 0) {
                    System.out.println("Reader cannot read... Database Occupied");
                    wait();
                }
                readerCount++;
                dbOccupied = true;
                System.out.println("Reader " + readerCount + " is reading...");
//                Thread.sleep(1000);
            }
        }
    }

    public void readerExit() throws InterruptedException {
        while (true) {
            synchronized (this) {
                while (readerCount != 0) {
                    System.out.println("Reader " + readerCount + " is now exiting...");
                    readerCount--;
                }
                dbOccupied = false;
                notifyAll();
//                Thread.sleep(1000);

            }
        }
    }

    public void writerEnter() throws InterruptedException {
        while (true) {
            synchronized (this) {
                while (dbOccupied){
                    System.out.println("New writer cannot write... Database Occupied");
                    wait();
                }
                dbOccupied = true;
                writer=true;
                System.out.println("Writer is now writing.....");
//                Thread.sleep(1000);

            }
        }
    }

    public void writerExit() throws InterruptedException {
        while (true) {
            synchronized (this) {
                if (writer) {
                    System.out.println("Writer leaving database...");
                    writer=false;
                    dbOccupied = false;
                    notifyAll();
//        Thread.sleep(1000);
                }




            }
        }

    }
}

public class RW3 {
    public static void main(String[] args) throws InterruptedException {
        final RW rw= new RW();
        Thread t1= new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    rw.readerEnter();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t2=new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    rw.readerExit();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t3= new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    rw.writerEnter();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t4= new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    rw.writerExit();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
//        t1.setPriority(2);
//        t3.setPriority(10);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t1.join();
        t3.join();
        t2.join();
        t4.join();
    }
}

this is the first time im using stackoverflow for asking a question, and im blown away by the response!!!!! i absolutely love the community


Solution

  • You call the readEnter method from the main thread and it put the main thread to sleep hence blocked. In order to put the work to the reader threads themselves you need to organize everything in main thread then fire the reader threads through the main thread. You must call the readEnter method only from within the reader threads. I did not implemented the writer you are encouraged to do that. The order in which the threads start is not guaranteed since it depends the schedular. See the example code:

    
    class CriticalSec {
        private int readerCount = 0;
    
        public boolean readerEnter() throws InterruptedException {
            if(readerCount == 0) {
                readerCount++;
                Thread.sleep(5000);
                return true;
            }
            else if(readerCount == 1) {
                readerCount++;
                Thread.sleep(5000);
                readerCount = 0; // rewind to zero
                return true;
            }
            else {
                System.out.println("Both reader threads are busy, "+Thread.currentThread().getName()+" will not be executed");
                return false;
            }
        }
    
    }
    
    class Reader implements Runnable {
    
        private final CriticalSec cs;
    
        public Reader(CriticalSec criticalSec) {
            cs = criticalSec;
        }
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+" goes for reading...");
            try {
                String state = cs.readerEnter() ? " done reading" : " failed reading!";
                System.out.println(Thread.currentThread().getName()+state);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    public class RWProblem {
        public static void main(String[] args) {
            CriticalSec c = new CriticalSec();
    
            Reader r1 = new Reader(c);
            Reader r2 = new Reader(c);
            Reader r3 = new Reader(c);
    
            new Thread(r1, "Reader 1").start();
            new Thread(r2, "Reader 2").start();
            new Thread(r3, "Reader 3").start();
        }
    }
    

    The output is for one of the run:

    Reader 3 goes for reading...
    Reader 1 goes for reading...
    Reader 2 goes for reading...
    Both reader threads are busy, Reader 1 will not be executed
    Reader 1 failed reading!
    Reader 3 done reading
    Reader 2 done reading
    
    Process finished with exit code 0