首頁  >  問答  >  主體

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 天前660

全部回覆(3)我來回復

  • 天蓬老师

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

    writeSomething是synchronized方法,代表這個方法進入的時候會加鎖,也就是說只要writeSomething不返回,所有其它writeSomething和readSometing都得等著,結果你又在writeSomething裡面wait,所以就死鎖了。

    對於reader/writer問題,你需要的其實不是讀寫鎖,而是信號量或條件變數。

    回覆
    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.

    回覆
    0
  • PHPz

    PHPz2017-04-17 11:59:31

    你的i一定會到達max,所以writer一定會停,但Reader裡有while(true),所以一定在Thread-2-read:1000時死循環wait,max有一個賦值1000,另一個賦值100,看不懂你的邏輯。

    回覆
    0
  • 取消回覆