Home  >  Q&A  >  body text

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的情况了,但是会死锁,执行不完,,彻底晕了,求解救~~

怪我咯怪我咯2716 days ago629

reply all(3)I'll reply

  • 天蓬老师

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

    writeSomething is a synchronized method, which means that this method will be locked when entering. That is to say, as long as writeSomething does not return, all other writeSomething and readSometing have to wait. As a result, you wait in writeSomething again, so you die. Locked.

    For the reader/writer problem, what you need is not a read-write lock, but a semaphore or condition variable.

    reply
    0
  • 怪我咯

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

    "The problem is, the maximum capacity of the warehouse is 100, in this case it will exceed 100"
    -- Multiple writers should wake up each other. You can try putting wait in 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
     }
    

    If a writer is awakened by another writer, the size of the current arraylist may still be 100. If there is no while, the writer will then increase the size to 101.

    reply
    0
  • PHPz

    PHPz2017-04-17 11:59:31

    Your i will definitely reach max, so the writer will definitely stop, but there is a while(true) in the Reader, so it must wait in an infinite loop at Thread-2-read:1000. Max has one assignment of 1000 and another assignment. 100, I don’t understand your logic.

    reply
    0
  • Cancelreply