0

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

比如第一个reader进入数据库,进程休眠5秒,我想让第二个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();
    }
}

这是我第一次使用 stackoverflow 来提问,我被回答吓坏了!!!!!!我非常喜欢这个社区

4

1 回答 1

0

您从主线程调用该readEnter方法,它使主线程进入睡眠状态,因此被阻塞。为了将工作交给阅读器线程本身,您需要在主线程中组织所有内容,然后通过主线程触发阅读器线程。您只能从阅读器线程中调用该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
于 2021-10-11T19:54:17.897 回答