This question already has an answer here: Not thread safe methods of CuncurrentSkipListMap in Java                                                                    (1个答案)                                                                        3年前关闭。                    我有这么简单的代码:class B {//....}public class A { private ConcurrentSkipListMap<Long, B> map = new ConcurrentSkipListMap<>(); public void add(B b) { long key = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) / 60; //this area has bug if (map.containsKey(key)) { B oldB = map.get(key); // work with oldB } else { map.put(key, b); } //end this area }}因此,我可以从2个线程中获取密钥。然后,第一个线程转到else-path。然后第二个线程正在启​​动。但是第一个线程还没有增加价值。 最佳答案 将您标记为“此区域有错误”的区域包装在synchronized块中:synchronized (map) { if (map.containsKey(key)) { B oldB = map.get(key); // work with oldB } else { map.put(key, b); }}这样可以防止两个具有相同key值的线程同时访问该映射-但前提是所有对map的其他访问也都是synchronized和get(例如,您没有未同步的在该课程的其他地方)。请注意,这会阻止对地图的所有并发更新,这可能会造成不可接受的瓶颈。尽管可以使用map.get获取可以在其上进行同步的实例,但是没有保证可以缓存的输入范围。相反,您也许可以将Long.valueOf(key)映射到long缓存的值范围内(即-128至127),这将为您提供更细粒度的锁定,例如// Assuming that your clock isn't stuck in the 1960s...Integer intKey = Integer.valueOf((int)( (longKey % 255) - 128));synchronized (intKey) { // ...}(或者,当然,您可以维护自己的键缓存)。关于java - 如何解决此竞态条件错误? ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38706840/
10-12 04:08
查看更多