您的位置:首页 > 其它

多线程资源共享的问题

2015-04-23 15:34 232 查看
以此文来反驳网上一片博文:Java中Runnable和Thread的区别

http://blog.chinaunix.net/uid-20665441-id-310538.html,这两个哪个是原创不分了

Runnable并不能解决资源共享。

废话不多说,上代码:

public class Demo implements Runnable {
    private static final Logger logger = Logger.getLogger(Demo.class);

    String name;
    static Integer tickets = 20;

    public Demo(String name) {
        this.name = name;
    }

    public void run() {
        for (int i = 1; i <= 20; i++) {
            if (tickets > 0) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
                logger.info("我取票了" + ": " + tickets);
                tickets -= 1;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
                logger.info("==========我取走了" + ": " + tickets);
            }
        }
    }

    public static void main(String[] args) throws IOException {

        Demo demo = new Demo("hello");

        new Thread(demo).start();
        new Thread(demo).start();
        new Thread(demo).start();

    }
}
结果:

[Thread-1] 我取票了: 20  
[Thread-2] 我取票了: 20  
[Thread-0] 我取票了: 20  
[Thread-1] ==========我取走了: 17  
[Thread-2] ==========我取走了: 17  
[Thread-0] ==========我取走了: 17  
[Thread-1] 我取票了: 17  
[Thread-2] 我取票了: 16  
[Thread-0] 我取票了: 15  
[Thread-1] ==========我取走了: 14  
[Thread-2] ==========我取走了: 14  
[Thread-0] ==========我取走了: 14  
[Thread-1] 我取票了: 14  
[Thread-2] 我取票了: 14  
[Thread-0] 我取票了: 12  
[Thread-1] ==========我取走了: 11  
[Thread-2] ==========我取走了: 11  
[Thread-0] ==========我取走了: 11  
[Thread-1] 我取票了: 11  
[Thread-2] 我取票了: 10  
[Thread-0] 我取票了: 9  
[Thread-1] ==========我取走了: 8  
[Thread-2] ==========我取走了: 8  
[Thread-0] ==========我取走了: 8  
[Thread-2] 我取票了: 8  
[Thread-1] 我取票了: 8  
[Thread-0] 我取票了: 6  
[Thread-2] ==========我取走了: 5  
[Thread-1] ==========我取走了: 5  
[Thread-0] ==========我取走了: 5  
[Thread-1] 我取票了: 5  
[Thread-2] 我取票了: 5  
[Thread-0] 我取票了: 3  
[Thread-1] ==========我取走了: 2  
[Thread-2] ==========我取走了: 2  
[Thread-0] ==========我取走了: 2  
[Thread-2] 我取票了: 2  
[Thread-1] 我取票了: 2  
[Thread-0] 我取票了: 0  
[Thread-1] ==========我取走了: -1  
[Thread-2] ==========我取走了: -1  
[Thread-0] ==========我取走了: -1  
从上面结果看到,最后出现负数,所以仅仅依靠Runnable是不能解决资源共享问题的

那么如何解决呢?

办法1. 同步run()方法

public synchronized void run()

输出结果为:

[Thread-0] 我取票了: 20  
[Thread-0] ==========我取走了: 19  
[Thread-0] 我取票了: 19  
[Thread-0] ==========我取走了: 18  
[Thread-0] 我取票了: 18  
[Thread-0] ==========我取走了: 17  
[Thread-0] 我取票了: 17  
[Thread-0] ==========我取走了: 16  
[Thread-0] 我取票了: 16  
[Thread-0] ==========我取走了: 15  
[Thread-0] 我取票了: 15  
[Thread-0] ==========我取走了: 14  
[Thread-0] 我取票了: 14  
[Thread-0] ==========我取走了: 13  
[Thread-0] 我取票了: 13  
[Thread-0] ==========我取走了: 12  
[Thread-0] 我取票了: 12  
[Thread-0] ==========我取走了: 11  
[Thread-0] 我取票了: 11  
[Thread-0] ==========我取走了: 10  
[Thread-0] 我取票了: 10  
[Thread-0] ==========我取走了: 9  
[Thread-0] 我取票了: 9  
[Thread-0] ==========我取走了: 8  
[Thread-0] 我取票了: 8  
[Thread-0] ==========我取走了: 7  
[Thread-0] 我取票了: 7  
[Thread-0] ==========我取走了: 6  
[Thread-0] 我取票了: 6  
[Thread-0] ==========我取走了: 5  
[Thread-0] 我取票了: 5  
[Thread-0] ==========我取走了: 4  
[Thread-0] 我取票了: 4  
[Thread-0] ==========我取走了: 3  
[Thread-0] 我取票了: 3  
[Thread-0] ==========我取走了: 2  
[Thread-0] 我取票了: 2  
[Thread-0] ==========我取走了: 1  
[Thread-0] 我取票了: 1  
[Thread-0] ==========我取走了: 0  


办法2. 同步tickets?这种方法貌似很行哦(⊙o⊙),Really?

public void run() {
    for (int i = 1; i <= 20; i++) {
        synchronized (tickets) {
            if (tickets > 0) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
                logger.info("我取票了" + ": " + tickets);
                tickets -= 1;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
                logger.info("==========我取走了" + ": " + tickets);
            }
        }
    }
}
输出结果为:

[Thread-0] 我取票了: 20  
[Thread-0] ==========我取走了: 19  
[Thread-2] 我取票了: 19  
[Thread-0] 我取票了: 19  
[Thread-2] ==========我取走了: 17  
[Thread-0] ==========我取走了: 17  
[Thread-2] 我取票了: 17  
[Thread-1] 我取票了: 16  
[Thread-1] ==========我取走了: 15  
[Thread-2] ==========我取走了: 15  
[Thread-0] 我取票了: 15  
[Thread-1] 我取票了: 15  
[Thread-0] ==========我取走了: 13  
[Thread-1] ==========我取走了: 13  
[Thread-1] 我取票了: 13  
[Thread-2] 我取票了: 13  
[Thread-1] ==========我取走了: 11  
[Thread-2] ==========我取走了: 11  
[Thread-0] 我取票了: 11  
[Thread-1] 我取票了: 11  
[Thread-1] ==========我取走了: 9  
[Thread-0] ==========我取走了: 9  
[Thread-1] 我取票了: 9  
[Thread-2] 我取票了: 9  
[Thread-1] ==========我取走了: 7  
[Thread-2] ==========我取走了: 7  
[Thread-0] 我取票了: 7  
[Thread-2] 我取票了: 7  
[Thread-2] ==========我取走了: 5  
[Thread-0] ==========我取走了: 5  
[Thread-2] 我取票了: 5  
[Thread-1] 我取票了: 5  
[Thread-2] ==========我取走了: 3  
[Thread-1] ==========我取走了: 3  
[Thread-2] 我取票了: 3  
[Thread-0] 我取票了: 2  
[Thread-2] ==========我取走了: 1  
[Thread-0] ==========我取走了: 1  
[Thread-2] 我取票了: 1  
[Thread-1] 我取票了: 1  
[Thread-2] ==========我取走了: -1  
[Thread-1] ==========我取走了: -1  
上面输出结果中,两个线程同时进来取票,最后出现负数,貌似是可以说明Integer不支持线程同步的,

因为 tickets-- 等同于tickets = new Integer(tickets-1),tickets早已不是原来的那个tickets。所以方法2是行不通的。

但是,如果存放“票”的是List却是完全可以的!

博主刚开始学线程,有误之处,欢迎指正!~

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: