Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java可视性和同步-Java示例中的思考_Java_Multithreading - Fatal编程技术网

Java可视性和同步-Java示例中的思考

Java可视性和同步-Java示例中的思考,java,multithreading,Java,Multithreading,我现在读了《用Java思考》,关于原子性和可见性的一章。有一个例子我不明白 public class SerialNumberGenerator { private static volatile int serialNumber = 0; public static int nextSerialNumber() { return serialNumber++; } } class CircularSet { private int[] arr

我现在读了《用Java思考》,关于原子性和可见性的一章。有一个例子我不明白

public class SerialNumberGenerator {
    private static volatile int serialNumber = 0;

    public static int nextSerialNumber() {
        return serialNumber++;
    }
}

class CircularSet {
    private int[] array;
    private int len;
    private int index = 0;

public CircularSet(int size) {
    array = new int[size];
    len = size;
    for (int i = 0; i < size; i++) {
        array[i] = -1;
    }
}

synchronized void add(int i) {
    array[index] = i;
    index = ++index % len;
}

synchronized boolean contains(int val) {
    for (int i = 0; i < len; i++) {
        if (array[i] == val)
            return true;
    }
    return false;
}

我不明白这怎么可能。即使是方法nextSerialNumber()也不同步,所有线程都会生成不同的值每个线程都有自己的串行值,并且每个都不同。那么,如何才能找到重复的。我无法想象线程的执行情况。

这个例子表明,增量后操作符不是原子的,也不是线程安全的

在这段代码中发生的是:

  • 启动多个(最多100个)线程,每个线程执行相同的代码
  • 在无限循环中:
    • 调用一个未同步的方法nextSerialNumber,该方法返回对静态变量调用后增量运算符的结果
    • 调用synchronized方法contains,该方法检查返回值是否存在于基础集合中
    • 如果是,则程序终止
    • 如果不是,则将该值添加到基础集合
如果增量后操作是线程安全的,那么程序将永远不会打印“复制”,也永远不会终止, 因为每个线程将获得不同的序列号值。这不是两个线程的情况 可能会得到完全相同的序列号值

private static final int SIZE = 10;
private static CircularSet serials = new CircularSet(1000);
private static ExecutorService exec = Executors.newCachedThreadPool();

static class SerialChecker implements Runnable {

    @Override
    public void run() {
        while (true) {
            int serial = SerialNumberGenerator.nextSerialNumber();
            if (serials.contains(serial)) {
                System.out.println("Duplicate: " + serial);
                System.exit(0);
            }
            serials.add(serial);
        }
    }
}

public static void main(String[] args) throws Exception {
    for (int i = 0; i < SIZE; i++) {
        exec.execute(new SerialChecker());
    }
}
Duplicate: 228