问一下下面这两段代码的区别:MyRunnable mr1 = new MyRunnable();
MyRunnable mr2 = new MyRunnable();
Thread t1 = new Thread(mr1);
Thread t2 = new Thread(mr2);
MyRunnable mr = new MyRunnable();
Thread t1 = new Thread(mr);
Thread t2 = new Thread(mr);做了一个线程同步的例子,第一段不行,第二段才行。
可不可以解释一下?

解决方案 »

  1.   

    第一段是两个线程调用的是两个不同的对象的run()方法,他们之间不存在共享的东西。
    第二段是两个线程调用的一个对象的run()方法,如果run()方法之前有synchronized 关键字修饰的话,他们之间共享 mr 这个对象。
      

  2.   


    synchronized 修饰后,应该是线程同步的吧,t1,t2 传递的都是mr,本身就已经共享了这个对象了。
      

  3.   

    楼主,你没有搞清楚并发的基本原理。什么时候会遇到并发的问题呢?
    只有一种情况:
        当一个类的实例被多个线程同时访问的时候:
        情况1:该实例的属性,被多个线程同时修改和读取,这个时候才会有并发情况下状态不一致的问题。解决这个问题的方法就是:使用同步的锁机制,或者看看该变量是不是能采用Atomic原子的类实例进行替换。
        情况2:该实例的属性,并没有被并发访问的方法所修改,这个方法是可以并发访问的,是线程安全的(这里要注意,防止当前实例的this溢出,否则也是非线程安全的)。或者该属性的类型是个 final 类型的(final的属性,只能在构造器里面进行初始化,就防止了它的再次修改)。这样的类的这些都是线程安全的。
    你的代码:MyRunnable mr1 = new MyRunnable();// MyRunnable的实例: mr1
    MyRunnable mr2 = new MyRunnable();// MyRunnable的实例: mr2
    //这里是2个实例,每个实例被放入了独立的线程。这样就不存在并发的问题,因为不存在共享的实例。
    //你这样的访问,可以很好的解决并发问题的资源共享出现的状态不一致的问题。这也是Java并发编程中的一种解决方案:“线程封闭”。这样解决问题的优点是:不存在共享的实例,就不存在并发引起的问题,使得编程更加容易。缺点是:这样的MyRunnable的实例很多的情况下,会出现内存的膨胀。
    Thread t1 = new Thread(mr1);
    Thread t2 = new Thread(mr2);你的下面的代码:MyRunnable mr = new MyRunnable(); //MyRunnable的实例: mr 这里只有一个实例,就有可能出现并发的问题。
    Thread t1 = new Thread(mr);
    Thread t2 = new Thread(mr);你可以看看《Java并发编程实战》,看完了,对并发的问题应该就不大了。