java并发问题

时间:2014-07-08 12:51:54

标签: java concurrency

为什么n有时等于1或2

private static int n = 0;

private static Thread t1, t2;

private synchronized static void increment() {
    n++;
}

public static void main(String[] args) {
    t1 = new Thread(new Runnable() {
        public void run() {
            increment();
        }
    });

    t2 = new Thread(new Runnable() {
        public void run() {
            t1.start();
            increment();
        }
    });

    t2.start();

    try {
        t2.join();
    } catch(InterruptedException e) {
        e.printStackTrace();
    }

    System.out.println(n);
}

增量方法是否只允许一个线程在任何给定时刻执行它?

也许它是调试器,似乎当我正常运行它时我总是得到2但是当我调试代码时它有时会返回1.

3 个答案:

答案 0 :(得分:8)

确实如此,但它可能以任何顺序发生。您只需等待t2完成,但不能等待t1完成。

等待t1

答案 1 :(得分:3)

private static int n = 0; 

private static Thread t1, t2;

private synchronized static void increment() {  // Lock will be on the "class" Object
    n++;
}

public static void main(String[] args) {
    t1 = new Thread(new Runnable() {
        public void run() {
            increment();
        }
    });

    t2 = new Thread(new Runnable() {
        public void run() {
            t1.start();           
// t1 starts after t2. Now, t1's increment might also be called or t2's increment() might also be called. If t2 calls increment(), then the join() method below (you are joining the in the main thread) will be completed and "n" will be printed (if t1 is not getting appropriate time of execution..)
            increment();
        }
    });

    t2.start();           // t2 starts first

    try {
        t2.join();
    } catch(InterruptedException e) {
        e.printStackTrace();
    }

    System.out.println(n); // increment() might not have been called by t1
}

无法保证一个线程会在另一个线程之前执行(即使是同步条件..)。因此,您可以在t1和t2上join。这将确保您始终以2输出。

答案 2 :(得分:1)

我想如果increment run方法中的t2调用发生在increment t1方法t1之前run } n方法,然后t2被锁定,到时间t1结束时,n可能仍在运行,但您正在打印t2t1的增量结束之前递增t2

澄清:

  • t2开始
  • t1产生t2
  • incrementt1有机会
  • 之前调用n
  • t2increment的{​​{1}}
  • 期间被锁定
  • Threadt2有机会t1之前加入increment
  • Threadn有机会t1之前打印increment