黑马程序员技术交流社区

标题: 多线程的问题 [打印本页]

作者: 曾祥旭    时间: 2013-3-27 07:39
标题: 多线程的问题
本帖最后由 曾祥旭 于 2013-3-27 11:31 编辑

class Resource{
        String name;
        String sex;
}
class Input implements Runnable{
        Resource r;
        Input(Resource r){
                this.r=r;
        }
        public void run(){
                int x=0;
                while(true){
                        synchronized(Resource.class){
                                if(x==0){
                                        r.name="mike";
                                        r.sex="man";
                                }
                                else{
                                    r.name="丽丽";
                                    r.sex="女女女女女女";
                                }
                        }
                        x=(x+1)%2;
                }
        }
}
class Outer implements Runnable{
        Resource r;
        Outer(Resource r){
                this.r=r;
        }
        public void run(){
                while(true){
                        synchronized(Resource.class){//虽然输入线程同步,但是输出的线程也是需要同步的
                        System.out.println(r.name+"-->"+r.sex);
                        }
                }
        }
}
public class Test{
        public static void main(String[] args){
                //创建资源
                Resource r=new Resource();
                //创建任务
                Input in=new Input(r);
                Outer out=new Outer(r);
                //创建线程,执行路径。
                Thread t1=new Thread(in);
                Thread t2=new Thread(out);
                //开启线程
                t1.start();
                t2.start();
        }
}

在上述代码中,产生的结果有成片出现相同的name与sex的情况,我知道当输入时候,Input抢到执行权,它可以成片的往里面输入数据,但是,为什么可以取出成片的数据结果呢?之前输入的数据不是被后来输入的数据进行覆盖了吗?如果覆盖,就不能取出成片出现的结果啊,如果没有覆盖,那么存储的数据的位置在哪,不过,给我的感觉是覆盖了之前输入的数据的。求解?(本人电脑是单核,那么CPU在快速切换的时候,Input抢到执行权,Output也就不能输出,因此,排除了t1与t2线程同时执行的情况,那么会不会是这样,t1线程执行的是mike这组数据,t2线程执行的是输出,t1与t2线程在不停的输入与输出同一组数据?)有没有覆盖这种情况呢?
作者: 王浩威    时间: 2013-3-27 09:00
哈哈。没学到那呢,不好意思奥
作者: HM朱蛟    时间: 2013-3-27 09:06
楼主你好

希望可以帮到你

问题:为什么会出现一大片一大片的  男那女女 这样的情况?
分析:
当某一个线程获得执行权的时候,并不会只输出1次,CPU是随机切换的,所以只有在CPU在某一个时刻切换到另一个线程时候,
才会终止当前,而后继续大片片的执行另一个线程。总体来说就是线程并发的抢占性和CPU处理数据的随机性共同造成的这样的局面。
解决:
1:给资源类加个标记。类似与开关,真代表有货,假代表没货。

2:input类,同步代码块里,判断:
若有货(标记为真)则不拉煤进去(给我在外面等着wait()),
若没货,(标记为假),兄弟们给我拉煤进去(往里存数据),
存完后记得记录下,说明里头有货了(flag=true),说明里头有货了,哥们儿不要再往里存了。
3:output类,同步代码块里:判断,
若没货,哥们儿在外面等(flag=非真),货都没有咱取不了啊。
若有货,哥们就进去取,(flag=非假), 有货哥们儿才能进仓库取啊,但是取完后记录下,取完后里面没货了(flag=false) 哥们儿些别往仓库里冲了。
作者: 王瑞    时间: 2013-3-27 09:08
看了半天,才看懂,下次建议用代码粘贴,不要直接粘贴呵呵。下面是我的解释,你看看是不是这样的:
首先,你这个程序只有个2个线程
                t1.start();
                t2.start();
对吧?
ti是输入线程,t2是输出线程。虽然同时运行,但是t1的输入线程已经锁住了,他的输入时,不可能出现mike和女这种情况的。所以输入的结果一定是mike。。man,丽丽和女女。
t2虽然锁住了,但是因为t1输入的时候不会出现抢线程的情况,t2输出是一片一片的。

至于你说的为什么覆盖老师貌似也没多讲啊。我的理解是只要执行多线程,运行start()线程就会一直执行run方法的,每执行一个run方法,就建立一个对象,这个对象应该是在堆内存中new run()吧?不知道对不对,个人感觉是这样~~~~
有疑问回复一下~

作者: 寇弘禄    时间: 2013-3-27 10:45
因为Input和Outer的同步代码块使用的是同一个锁,所以某个时间只能执行他们两个中的一个,也就是输入的时候不能同时在输出。
当t1线程抢到执行权后一直在进行着输入,输入mike man和丽丽 女交替进行,并将值保存在共享数据r 的neme和sex里,新值会覆盖原来的值。
当某一时刻t2抢到执行权,就会一直打印最后保存在r里面的name和sex,所以就会成片的打印同样的结果。




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