public class Threads1 {
int x = 0; public class Runner implements Runnable {
public void run() {
int current = 0;
for (int i = 0; i < 4; i++) {
current = x;
System.out.println(current + ", ");
x = current + 2;
}
}
} public static void main(String[] args) {
new Threads1().go();

} public void go() {
Runnable r1 = new Runner();
new Thread(r1).start();
new Thread(r1).start();
}
}
我认为运行结果是0,2,4,6,8,10,12但是我的机子上跑出来是0,2,4,6,0,2,4,6,有人能告诉我应该怎么样去正确地理解这段代码么,不是只有一个Thread1对象么threadjava

解决方案 »

  1.   

    变量x是线程独享的,不是共享数据,如果想成为共享数据,改为static的静态变量。
      

  2.   

    不是吧,如果改为static的话,输出的结果还是和原来一样。但是如果把run改为public synchronized void run() {就能达到输出
    0, 2, 4, 6, 8, 10, 12, 14,
      

  3.   

    哦。更正一下, 变量x是共享数据。
    刚才没注意看程序。共享数据,没有进行读写保护,所以产生,数据不同步的现象。所以,其实,任何情况都有可能发生的。至于楼主说的那种情况,很可能是:
    1.两个线程同时进入run方法;
    2.当运行至输出语句是,由于System.out对象的print方法,属于IO操作,这个对象发生竞争;
    3.有一个线程得到System.out对象的锁,进行输出操作;另一个线程被阻塞直到锁被释放;
    4.得到锁的线程进行输出,首次输出为0,释放锁;
    5.释放锁后,当前线程进行后续代码的执行,进入下次循环;另一个线程被唤醒,进入就绪状态;
    6.进入就绪状态的线程,在没有分到时间片的时候,是没有运行机会的;
    7.输出0的线程,由于时间片没有用完,进入循环,进行输出,由于另一线程没有运行机会,所以,没有再次进行锁竞争;
    8.4次循环,估计在一个线程时间片内是能够搞定的,所以,谁先输出的0 ,谁就会吧后面的2,4,6输完;
    9.一个线程输出完毕后,退出,另一线程得到运行机会,进行输出,由于这个线程是锁竞争被阻塞的,所以,代码要从输出语句开始执行,并且,阻塞前current是0,所以,后面也会输出2,4,6
      

  4.   

    0,2,4,6,8,10,12,14
    这个序列的产生,
    可能会是:
    两个线程都就绪了,但没进入run方法,
    这时,操作系统调度一个线程进入run方法,一个时间片过后,0,2,4,6产生了,
    操作系统调度另一个线程进入run方法,输出8,10,12,14
      

  5.   

    楼主,我想了好久,应该是这样的。
    0,2,4,6,0,2,4,6,这种情况:
    首先这是对同一个对象进行操作的两个进程,Thread[Thread-0,5,main]和Thread[Thread-1,5,main],首先Thread-0获得CPU,当第八行运行完毕后突然被中断了,此时current就是0,被存储了下来。然后Thread-1获得CPU,这个线程全部执行完毕打印出0,2,4,6, ,这时候才轮到Thread-0继续执行,此时current是上次运行时保存下来的0,所以打印0,2,4,6.而0, 2, 4, 6, 8, 10, 12, 14, 这种情况:
    首先Thread-0执行完毕,打印出0,2,4,6, 然后是Thread-1执行打印出0,2,4,6,  其实可能性很多,主要看线程合适被中断。
      

  6.   

    你把synchronized关键字加在方法上是起不到多线程的功能的,因为第一个线程进入synchronized代码的for 循环之后一直运行完成才允许第二个线程使用(即使在synchronized 中添加睡眠代码);synchronized 需要加在for循环中并且在synchronized 中加上睡眠代码好让其他线程有机会运行。
      

  7.   

    主要就是数据不同步呗,给LZ举个例子,两个窗口同时卖票操作的票源是100张,那么,当1号窗口卖出1号票时,2号窗口就不可能再出一张1号票,要是那样就数组错乱了,所以这个程序最好加锁,利用这个关键字synchronized   
    或者   private Lock lock = new ReentrantLock(); private Condition condition_x = lock.newCondition();
      

  8.   

    new Thread1()是匿名对象,也就是每次产生的地址都可能不一样.
      

  9.   

    楼主把current拿到run方法外面就好了,在这里是一个局部变量
      

  10.   

    一道OCJP的模拟题,我会那么无聊去折磨自己嘛~~~唉……休息去了
      

  11.   

    run 方法上加一个synchronized就好了,这个就是两个线程争夺资源时候的数据不一致问题吧,两个线程同时读取到了一个数据,出现脏数据...
      

  12.   

    看来楼主也在搞OCJP啊~~我也在备考中~~