Rumah  >  Soal Jawab  >  teks badan

java - 多线程【读者写者】问题

这是个读者写者程序~

public class Main {

    Factory fa = new Factory();
        //主程序
    public static void main(String[] args) {
        Main mm = new Main();
        Writer writer = mm.new Writer();

        new Thread(writer).start();
        new Thread(writer).start();

        new Thread(mm.new Reader()).start();
    }
    //写者
    class Writer implements Runnable {
        int max = 1000;//总共写1000次
        int i = 0;

        @Override
        public void run() {
            while (true && i < max) {
                fa.writeSomething();
                ++i;
            }
        }

    }
    //读者
    class Reader implements Runnable {
        @Override
        public void run() {
            while (true) {
                fa.readSomething();
            }
        }
    }

    class Factory {
        List<Integer> repo = new ArrayList<Integer>();//仓库
        int max = 100, min = 0, isn = 0;//仓库最大值、最小值、图书编号

        //写
        public synchronized void writeSomething() {
            if (repo.size() == max) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } 
            System.out.println(Thread.currentThread().getName() + "-write:"
                        + isn + "/ Size: " + repo.size());
            repo.add(new Integer(isn++));
            this.notify();

        }
        //读
        public synchronized void readSomething() {
            if (repo.size() == min) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + "-read:"
                    + repo.get(0));
            repo.remove(0);
            this.notifyAll();
        }
    }

}

一个写者,多个读者的时候这个程序是没问题的
多个写者,一个读者的时候就出问题了,问题在与,仓库最大容量为100,这种情况下会超过100,我感觉问题出在多个写者会相互唤醒,不知道我分析的对不对,所以改了一下writeSomething(),如下:

        // 写
        public synchronized void writeSomething() {
            if (repo.size() >= max) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println(Thread.currentThread().getName() + "-write:"
                        + isn + "/ Size: " + repo.size());
                repo.add(new Integer(isn++));
                this.notify();
            }
        }

这样的确不会出现容量超过100的情况了,但是会死锁,执行不完,,彻底晕了,求解救~~

怪我咯怪我咯2765 hari yang lalu663

membalas semua(3)saya akan balas

  • 天蓬老师

    天蓬老师2017-04-17 11:59:31

    writeSomething是一个synchronized方法,代表这个方法进入的时候会加锁,也就是说只要writeSomething不返回,所有其它writeSomething和readSometing都得等着,结果你又在writeSomething里面wait,所以就死锁了。

    对于reader/writer问题,你需要的其实不是读写锁,而是信号量或者条件变量。

    balas
    0
  • 怪我咯

    怪我咯2017-04-17 11:59:31

    "问题在与,仓库最大容量为100,这种情况下会超过100"
    -- 应该是多个写者会相互唤醒. 你把wait放在while里试试:

    In other words, waits should always occur in loops, like this one:

     synchronized (obj) {
         while (<condition does not hold>)
             obj.wait(timeout);
         ... // Perform action appropriate to condition
     }
    

    如果一个写者 被另一个写者唤醒, 当前的arraylist的size可能还是100. 如果没有while, 这个写者接着会把size增为101.

    balas
    0
  • PHPz

    PHPz2017-04-17 11:59:31

    你的i一定会到达max,所以writer一定会停,但Reader里有while(true),所以一定在Thread-2-read:1000时死循环wait,max有一个赋值1000,另一个赋值100,看不懂你的逻辑。

    balas
    0
  • Batalbalas