Java可视性和同步-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
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