黑马程序员技术交流社区

标题: 为何两个子线程都输出了100? [打印本页]

作者: Great_Man    时间: 2014-6-18 12:03
标题: 为何两个子线程都输出了100?
废话少说,直接上代码先。

01 class ThreadDemo{
02     //    定义全局变量
03     private static int x = 100;
04     public static void main(String[] args){
05         //创建两个线程
06         Demo d0 = new Demo();
07         new Thread(d0,"线程0").start();
08         Demo d1 = new Demo();
09         new Thread(d1,"线程1").start();
10     }
11     //线程Demo
12     static class Demo implements Runnable{//extends Thread{
13         //实现Runnable中的run方法。
14         public void run(){
15             for(;x>0;x--)
16                 System.out.println(Thread.currentThread().getName()+"  "+x);
17         }   
18    }
19 }

程序运行结果为:

线程1  100

线程0  100

线程1  99

线程0  98

线程1  97

线程0  96

……

分析:

开辟两个子线程,当线程1进入打印输出100时,线程0也进入打印100,然后x--,下一步将打印99。
问题:
为什么后面不会一起打印99呢?

另外:
我知道,如果这样做:

for(;x>0;)System.out.println(Thread.currentThread().getName()+"  "+x--);

将会从100到1全部单次输出,不会重复输出。

可见这样子,两个字线程不会同时进行执行System.out.println()。

作者: 倪大大    时间: 2014-6-18 14:29
首先你这个程序安全性有问题,两个线程同时访问同一个变量,是肯定会出现错误信息的,两个100就是体现.
至于为什么后面不会出现两次99 . 是因为 最开始两个线程开启后第一次执行for循环的时候,在两个线程都还没有执行最后x--操作的时候,都先执行了打印语句,所以就会出现两个100, 这以后每个线程都必定会顺序执行-1操作,所以不会再出现重复, 有点不好讲这意思
  当你把x-- 放到输出语句的时候 也是会出现相同100的情况 你可以多试验几次 我已经试验过了.
  你放下来 其实也一样  打印语句执行完后, 再执行-1操作,  所以
System.out.println(Thread.currentThread().getName()+"  "+x--); 这句其实是两个步骤.

作者: Great_Man    时间: 2014-6-18 14:58
倪大大 发表于 2014-6-18 14:29
首先你这个程序安全性有问题,两个线程同时访问同一个变量,是肯定会出现错误信息的,两个100就是体现.
至于 ...

非常感谢你的回答。下面是我对程序的改进。
Object p = new Object();
                public void run(){
                        synchronized(p){
                        for(;x>0;x--)
                                System.out.println(Thread.currentThread().getName()+"  "+x);
                        }
                }
结果没有变化,同样输出了两个100.唯一的变化是,输出不是顺序递减的,比如97 98 96 94 95……
我进行了设置同步代码块,还是两个100,为何呢?
作者: 倪大大    时间: 2014-6-18 19:51
Great_Man 发表于 2014-6-18 14:58
非常感谢你的回答。下面是我对程序的改进。
Object p = new Object();
                public void run(){

因为你的P 是局部变量,你new了两个Demo 其实是两个P  锁都不一样 怎么能同步?
你这个P要定义成全局变量 让两个类共享
作者: 不去会死    时间: 2014-6-18 19:55
这是个概率问题,第一次的概率比较大,后面打印相同的概率比较小,但还是有可能的,你可以试试更大的数
作者: rover0321    时间: 2014-6-18 20:00
你可以回忆一下毕老师说的那两个条件:
1.两个线程
2.同一把锁

你改进后的代码不符合第二个条件。
作者: Great_Man    时间: 2014-6-20 23:45
倪大大 发表于 2014-6-18 19:51
因为你的P 是局部变量,你new了两个Demo 其实是两个P  锁都不一样 怎么能同步?
你这个P要定义成全局变量  ...

你说得对,我已经搞定了
作者: Great_Man    时间: 2014-6-20 23:46
rover0321 发表于 2014-6-18 20:00
你可以回忆一下毕老师说的那两个条件:
1.两个线程
2.同一把锁

这是因为我创建了两个Runnable实例。
作者: rover0321    时间: 2014-6-21 11:12
Great_Man 发表于 2014-6-20 23:46
这是因为我创建了两个Runnable实例。

在你的代码中两个实例 就是用了两把不同的锁。
作者: 淡淡柠檬茶    时间: 2014-6-21 11:20
留个脚印 以后看




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2