奇怪的同步行为

时间:2014-12-16 12:36:28

标签: java multithreading thread-safety

class TestSync {
public static void main(String[] args) throws InterruptedException {
    Counter counter1 = new Counter();
    Counter counter2 = new Counter();
    Counter counter3 = new Counter();
    Counter counter4 = new Counter();

    counter1.start();
    counter2.start();
    counter3.start();
    counter4.start();

    counter1.join();
    counter2.join();
    counter3.join();
    counter4.join();

    for (int i = 1; i <= 100; i++) {
        if (values[i] > 1) {
            System.out.println(String.format("%d was visited %d times", i, values[i]));
        } else if (values[i] == 0) {
            System.out.println(String.format("%d wasn't visited", i));
        }
    }
}

public static Integer count = 0;
public static int[] values = new int[105];

static {
    for (int i = 0; i < 105; i++) {
        values[i] = 0;
    }
}

public static void incrementCount() {
    count++;
}

public static int getCount() {
    return count;
}

public static class Counter extends Thread {
    @Override
    public void run() {
        do {
            synchronized (count) {
                incrementCount();

                values[getCount()]++;
            }
        } while (getCount() < 100);
    }
}

}

这是一个在线课程的代码。我的任务是使这段代码只访问数组的每个元素一次(仅适用于1到100之间的元素)。所以我添加了简单的synchronized块来运行方法。如果在该语句中使用值,一切正常。但有了它,它不想工作。

有什么区别?这两个对象都是同一个类中的静态字段。此外,我试图让计数变得不稳定,但它没有帮助我。

PS:许多元素被访问了2次,其中一些甚至被访问了3次。如果在synchronized中使用值,则只访问一次所有元素!!!

1 个答案:

答案 0 :(得分:2)

整数是不可变的。你调用increment方法的那一刻,你得到一个新的对象,count变量的引用会被改变,从而导致一个问题。