有很多读卡器,但当编写器与HashMap java一起使用时就没有了

有很多读卡器,但当编写器与HashMap java一起使用时就没有了,java,multithreading,Java,Multithreading,关于这个领域,我已经慢慢地问了很多问题,但我的问题仍然存在。我也在寻求一些详细的答案(如果你够客气的话?)。所以我可以更清楚地理解这一点,也可以理解社区 这是我的问题。我有这张地图 private static volatile Map<Integer, Type> types; 私有静态易失映射类型; 并将静态吸气剂作为 static Type getType(final int id) { if (types == null) { synch

关于这个领域,我已经慢慢地问了很多问题,但我的问题仍然存在。我也在寻求一些详细的答案(如果你够客气的话?)。所以我可以更清楚地理解这一点,也可以理解社区

这是我的问题。我有这张地图

 private static volatile Map<Integer, Type> types;
私有静态易失映射类型;
并将静态吸气剂作为

static Type getType(final int id)
  {
    if (types == null)
    {
      synchronized (CLASSNAME.class)
      {
        if (types == null)
        {
          types = new HashMap<Integer, Type>();
          ....add items to the map 
        }
      }
    }      

    return types.get(id);
  }
静态类型getType(最终int-id)
{
如果(类型==null)
{
已同步(CLASSNAME.class)
{
如果(类型==null)
{
types=newhashmap();
…将项目添加到地图中
}
}
}      
返回类型.get(id);
}
这段代码中的问题是,第一个线程可以初始化类型,这样它就不再为null。当第一个线程向映射添加值时,第二个线程可以从中检索数据。这意味着数据已损坏

我看到,通过同步整个方法可以避免这种情况,但不可能有多个读卡器。这是一个一次性的地图建设,将不会有任何修改。因此,多个读者是必不可少的

我们也可以使用Collections.synchronizeMap,但如果我没记错的话,它也不允许并发读卡器。我试过了,但是ConcurrentHashMap也不能解决这个问题。可能是因为它的独立分区锁定行为

简单地说,我需要的是在完全创建地图之前不阅读,然后应该可以进行多次阅读。 有人有办法吗?
谢谢。

您的问题有一个简单的解决方案。使用临时变量,以便只要映射未完全填充,引用
类型
即为
null
。如果您以这种方式更改代码,那么它是线程安全的,并且非常高效

static Type getType(final int id) {
    if (types == null) {
        synchronized (CLASSNAME.class) {
            if (types == null) {
                HashMap<Integer, Type> temp = new HashMap<>();
                // populate temp
                types = temp;
            }
        }
    }
    return types.get(id);
}
看看这个模式。Java 8中有一些特定的实现,但如果您不打算很快采用,请查看Guava的,特别是:

private final ConcurrentMap<Map<Integer, Type> types = new MapMaker()
          .makeComputingMap(new Function<Integer, Type>() {
                    public Graph apply(Type key) {
                           return loadForType(key);
                    }
           });

private final concurrentmap按照您编写它的方式,可以进行多次读取,但在第一个线程初始化时不会。初始化完成后,后续线程可以同时读取,因为类型将!=无效的您唯一的其他选择是不惰性地实例化。此外,您应该将类变量类型指定为同步块中的最后一步,以确保读线程不会得到空映射。哇,这是正确的吗?。似乎能很好地满足我的要求,但同步方面的要求不多:)。期待接受这一点,但是否有任何java同步解决方案?只是出于好奇。
class types
{
private:
    std::once_flag _flag;
    std::map<int, type> _map;
public:
    auto get_type(int id) -> const type&
    {
        std::call_once(_flag, [this] { _map = populated_map(); });
        return _map.find(id)->second;
    }
};
private final ConcurrentMap<Map<Integer, Type> types = new MapMaker()
          .makeComputingMap(new Function<Integer, Type>() {
                    public Graph apply(Type key) {
                           return loadForType(key);
                    }
           });