如何解决为什么在 CopyOnWriteArrayList 或 synchronizedList() 上的写操作之前读会导致不一致?
我正在研究并发性,我想了解为什么在多线程场景中先读后写操作:copyOnWriteArrayList
或 synchronizedList()
会导致非确定性行为。
代码如下:
public class LoadBalancer {
private static final Integer MAX_PROVIDERS_SIZE = 10;
private final List<String> registeredProviders;
private LoadBalancer(List<String> initialProviders) {
if (!(initialProviders.size() == new HashSet<>(initialProviders).size())) {
throw new ProviderAlreadyExists();
}
this.registeredProviders = Collections.synchronizedList(initialProviders);
}
public static LoadBalancer of(List<String> registeredProviders) {
return new LoadBalancer(registeredProviders);
}
public LoadBalancer registerProvider(String provider) {
if (registeredProviders.size() >= MAX_PROVIDERS_SIZE) {
throw new ProvidersLengthExceeded();
} else {
registeredProviders.stream().filter(p -> p.equals(provider))
.findFirst()
.ifPresent(p -> {
throw new ProviderAlreadyExists();
});
registeredProviders.add(provider);
System.out.println("SIZE" + registeredProviders.size());
}
return this;
}
public List<String> getRegisteredProviders() {
return registeredProviders;
}
}
public class ProvidersLengthExceeded extends RuntimeException{
public ProvidersLengthExceeded() {
super("The maximum providers size is 10.");
}
}
public class ProviderAlreadyExists extends RuntimeException{
public ProviderAlreadyExists() {
super("The provider already exists.");
}
}
这是测试:
@Test
public void concurrencyCheck() throws InterruptedException {
List<String> testProviders = IntStream.rangeClosed(0,8).mapToObj(index -> index + "")
.collect(Collectors.toList());
LoadBalancer lb = LoadBalancer.of(testProviders);
ExecutorService service = Executors.newFixedThreadPool(10);
IntStream.range(0,100).forEach(i -> service.submit(() -> {
lb.registerProvider(UUID.randomUUID().toString());
}));
Thread.sleep(10_000);
System.out.println(lb.getRegisteredProviders().size());
}
}
我想要的行为是我不能向列表中添加超过 MAX_PROVIDERS_SIZE
项。
使用上面的代码,我得到以下输出:
SIZE11
SIZE10
SIZE13
SIZE12
13
SIZE10
10
为什么会这样?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。