先进先出读写器java

x3naxklr  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(333)

在这里,我们用java构建了一个并发程序,在这个程序中,我们模拟了一个从中读取和写入的数据库。我们有20个同时阅读的读者和2个不同时阅读的作者。
读者开始阅读,写完之后,作家开始写作,这给作家造成了饥饿感。
我得到的结果是:

Reader 15 started reading
Reader 5 started reading
Reader 2 started reading
Reader 7 started reading
Reader 15 finished reading
Reader 5 finished reading
Reader 16 started reading
...
...
Writer 21 started writing
Writer 21 finished writing
Writer 20 started writing
Writer 20 finished writing

所以,我一直在尝试对这个程序执行fifo命令,以消除饥饿。例如,输出应该是r1、w1、r2、r3、r4、w2(r—reader,w—writer)。我被困在这一点上,我不知道是否改变我的算法与否。提前谢谢!

import java.util.concurrent.ThreadLocalRandom;

public class Runner {
    public static void main(String[] args) {
        try {
            runDB(20, 2, new BetterDB());
        } catch (InterruptedException ignored){}
    }

    static void runDB(int readersAmount, int writersAmount, DB database) throws InterruptedException {
        assert readersAmount > 0;
        assert writersAmount > 0;

        Thread[] threads = new Thread[readersAmount + writersAmount];

        for (int i = 0; i < readersAmount; i++){
            threads[i] = new Thread(new Reader(database, i));
        }
        for (int i = readersAmount; i <  readersAmount + writersAmount; i++){
            threads[i] = new Thread(new Writer(database, i));
        }

        for (Thread thread : threads){
            thread.start();
        }
        for (Thread thread : threads){
            thread.join();
        }
    }
}

interface DB {
    void read(int readerID) throws InterruptedException;
    void write(int writerId);
}

class BetterDB implements DB {
    long READ_TIME = 500; // milliseconds
    long WRITE_TIME = 1000; // milliseconds

    int readers = 0;

    @Override
    public void read(int readerID) throws InterruptedException {
        synchronized (this) {
            readers++;
            System.out.printf("Reader %d started reading\n", readerID);
        }

        try {
            ThreadLocalRandom random = ThreadLocalRandom.current();
            Thread.sleep(random.nextLong(READ_TIME));
        } catch (InterruptedException ignored) {}

        synchronized (this) {
            readers--;
            System.out.printf("Reader %d finished reading\n", readerID);
            if (readers == 0) {
                this.notifyAll();
            }
        }
    }

    @Override
    public synchronized void write(int writerId) {
        try{
            while(readers > 0){
                this.wait();
            }
        } catch (InterruptedException ignored) {}

        System.out.printf("Writer %d started writing\n", writerId);
        try{
            ThreadLocalRandom random = ThreadLocalRandom.current();
            Thread.sleep(random.nextLong(WRITE_TIME));
        } catch (InterruptedException ignored) {}

        System.out.printf("Writer %d finished writing\n", writerId);
    }
}

class Reader implements Runnable {
    final long READER_DELAY = 500; // milliseconds
    private final DB database;
    private int id;

    Reader(DB database, int id){
        this.database = database;
        this.id = id;
    }

    @Override
    public void run() {
        try{
            ThreadLocalRandom random = ThreadLocalRandom.current();
            Thread.sleep(random.nextLong(READER_DELAY));
            database.read(id);
        } catch (InterruptedException ignored) {}
    }
}

class Writer implements Runnable {
    final long WRITER_DELAY = 400; // milliseconds
    private final DB database;
    private int id;

    Writer(DB database, int id){
        this.database = database;
        this.id = id;
    }

    @Override
    public void run() {
        try{
            ThreadLocalRandom random = ThreadLocalRandom.current();
            Thread.sleep(random.nextLong(WRITER_DELAY));
            database.write(id);
        } catch (InterruptedException ignored) {}
    }
}
e5njpo68

e5njpo681#

如果我理解你的意图,你希望你的作者能够暂停读者,让他们有机会写作?
现在,他们被淹没了。所有的读者都可以保持忙碌,因为有20个,他们都可以同时运行,而且他们都会暂停足够长的时间,以使一个作家能够获得同步锁的可能性非常低。
听起来您需要实现更复杂的锁定,例如“request two write”锁定。你可以让你的编剧增加锁,然后在完成后减少它。读卡器需要类似的逻辑,写卡器需要检查是否有写锁请求。

相关问题