java - 多线程【读者写者】问题
怪我咯
怪我咯 2017-04-17 11:57:31
0
3
657

这是个读者写者程序~

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

怪我咯
怪我咯

走同样的路,发现不同的人生

全部回复(3)
Peter_Zhu

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

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

刘奇

"问题在与,仓库最大容量为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.

PHPzhong

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

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!