java - 同步的奇怪行为

标签 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);
    }
}

}

这是一门在线类(class)的代码。我的任务是让这段代码只访问数组的每个元素一次(仅针对从 1 到 100 的元素)。所以我添加了简单的同步块(synchronized block)来运行方法。如果在该语句内使用值,则一切正常。但随着计数它不想工作。

有什么区别?这两个对象都是同一类中的静态字段。我也尝试过让 count 变得不稳定,但这对我没有帮助。

PS:很多元素被访问了 2 次,有些甚至被访问了 3 次。如果在同步中使用值,则所有元素仅被访问一次!!!

最佳答案

整数是不可变的。当您调用增量方法时,您会得到一个新对象,并且计数变量的引用发生变化,从而导致问题。

关于java - 同步的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27504828/

相关文章:

java - 解析系统属性,需要澄清

java - Java中根据monitor对象的特定属性同步线程

java - 如何正确使用Java Executor?

c++ - 堆上的专用 std::vector 是线程安全的吗?

multithreading - 无状态 session 线程安全吗?

c++ - std::lock_guard 导致未定义的行为

java - 如何根据 Predicate 过滤 Iterable?

java - Android - 保存到文本文件

Java - 如何在同一个文件中包含2个类?

c# - 线程——执行时间的模拟