看起来Java系统属性的迭代版本不是线程安全的。这可以通过以下代码进行验证
import java.io.FileWriter;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
public class JavaPropertiesTest {
public static void main(String[] args) throws Exception {
new Thread(() -> {
while (true) {
Properties properties = System.getProperties();
try (FileWriter fileOutputWriter = new FileWriter("/dev/null")){
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
fileOutputWriter.append(entry.getKey().toString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
Random gen = new Random();
while (true) {
System.getProperties().setProperty(Integer.toString(gen.nextInt()), Integer.toString(gen.nextInt()));
}
}).start();
}
}
clojure 1.8.x中的堆栈跟踪,并且对于最新版本依然如此
原因:在java.util.Hashtable$Enumerator.next(Hashtable.java:1387)处抛出java.util.ConcurrentModificationException,在clojure.lang.RT$4.invoke(RT.java:509)处触发,在clojure.lang.LazySeq.sval(LazySeq.java:40)处,在clojure.lang.LazySeq.seq(LazySeq.java:49)处,在clojure.lang.ChunkedCons.chunkedNext(ChunkedCons.java:59)处,在clojure.lang.ChunkedCons.next(ChunkedCons.java:43)处,在clojure.lang.RT.next(RT.java:688)处,在clojure.core$next4341.invokeStatic(core.clj:64)处,在clojure.core.protocols$naive_seq_reduce.invokeStatic(protocols.clj:63)处,在clojure.core.protocols$interface_or_naive_reduce.invokeStatic(protocols.clj:72)处,在clojure.core.protocols$fn6755.invokeStatic(protocols.clj:168)处,在clojure.core.protocols$fn6755.invoke(protocols.clj:124)处,在clojure.core.protocols$fn6710$G6705__6719.invoke(protocols.clj:19)处,在clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:31)处,在clojure.core.protocols$fn6732.invokeStatic(protocols.clj:75)处,在clojure.core.protocols$fn6732.invoke(protocols.clj:75)处,在clojure.core.protocols$fn6684$G66796697.invoke(protocols.clj:13)处,在clojure.core$reduce.invokeStatic(core.clj:6545)处,在clojure.core.server$parse_props.invokeStatic(server.clj:143)处,在clojure.core.server$start_servers.invokeStatic(server.clj:154)处,在clojure.core.server$start_servers.invoke(server.clj:154)处,在clojure.lang.Var.invoke(Var.java:379)处,在clojure.lang.RT.doInit(RT.java:482)处