Reader 作者使用 Java 线程时遇到问题

Reader writers problem using Java Threads

我一直在尝试在 Java 中解决 reader 编写器问题。但是当Thread.Sleep(5000)执行时,当前线程进程并没有中断。

比如第一个reader进入数据库,进程休眠5秒,我想让第二个reader进入数据库。但是在我的代码中,第二个 reader 仅在第一个 reader 醒来并离开数据库后才进入数据库

如何达到我想要的结果?

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();
    }
}

我刚开始学习Java,如果我的问题含糊不清,我很抱歉。我很乐意提供更多详细信息。

编辑:

在复习了一些重要概念并进行了大量练习之后,我想出了一个解决方案。有人可以看看它并告诉我它是否合适吗?我该如何改进它?

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();
    }
}

这是我第一次使用 Whosebug 提出问题,我对回答感到震惊!!!!!!我非常喜欢这个社区

您从主线程调用 readEnter 方法,它使主线程进入睡眠状态,因此被阻塞。为了将工作交给 reader 线程本身,您需要在主线程中组织所有内容,然后通过主线程触发 reader 线程。 您只能从 reader 个线程 中调用 readEnter 方法。我没有实施作家,我们鼓励您这样做。不能保证线程启动的顺序,因为它取决于调度。查看示例代码:


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();
    }
}

输出是运行之一:

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