我有一个从多个线程调用的简单方法;
@Override
public Bitmap getFullBitmap(Filter f, ProgressCallback<String> pc) {
// Requires synchronisation?
Bitmap bitmap = fullMap.get(f.id);
if(bitmap == null){
f.setProgressCallback(pc);
bitmap = f.e.evaluate(currentBitmap);
fullMap.put(f.id, bitmap);
}
return bitmap;
}
因为没有使用的对象是类的字段(除了fullMap),只需调用它或者一个线程可能会改变位图的值,例如,当方法执行时?
fullMap是一个SoftHashMap,它维护索引的Bitmap对象的SoftReferences,但是用于创建它的Filter的id。如果这是有道理的。
我没有遇到任何问题,但我认为我可能需要它。
如果不清楚,请询问澄清,这个问题在我脑海中有意义;)
修改
非常感谢! GAV
答案 0 :(得分:4)
2个主题可以同时访问地图fullMap
。两者都可以确定地图不包含同一个键的值,每个都创建一个,然后将其写回,从而插入两次键。
除了效率之外,这可能不是一个问题。然而,它可能会引起混淆,并且随着您的解决方案的发展可能在未来出现问题(将来创建这些对象的成本有多大?如果有人在不合适的地方复制/粘贴代码,会发生什么?)
我强烈建议同步上面的内容(很可能是fullMap
本身而不是包含对象,但在确定需要什么之前,更多上下文会有用)
答案 1 :(得分:2)
SoftHashMap.put本身可能不是线程安全的。 SoftHashMap不在标准库中,但WeakHashMap是,并且它未同步。除了在地图上同步方法之外,您可能希望使用Collections.synchronizedMap来确保其他方法不会同时修改地图。
答案 2 :(得分:1)
您绝对需要同步,因为您可以让两个线程决定f.id
不在地图中,构造然后添加一个。每个线程都将返回f.id
的差异实例,即使该地图仅包含最后完成的那个。
问题不在于变量bitmap
。这是线程安全的,因为它是单个线程的本地。但是,访问`fullMap - 我假设是该类的一个字段 - 需要同步,因为你正在做一个“如果没有”的事实。
假设构建位图的成本很高,最好的方法就是同步方法getFullBitmap()
。如果它构造起来非常便宜 - 比同步便宜 - 那么我建议总是构建新对象并在putIfAbsent
上进行ConcurrentMap
。但是当构造对象的代价很高时,这是一个坏主意。
答案 3 :(得分:0)
如果你的方法只使用传入的参数和局部变量,没有共享状态,那么我会说它是线程安全的,不需要同步。
线程安全必须担心可变的共享状态。 fullmap是该对象状态的一部分吗?如果是,那么您必须同步其访问权限。
答案 4 :(得分:0)
如果返回的Bitmap在方法之外修改,我会选择同步路径。你冒着2个线程访问上面方法的风险,而f.id上的Bitmap为null,都创建一个并将其添加到地图,第二个覆盖Map中的第一个。现在你有两个,一个将被thread-1修改但是一旦thread-1完成其处理就会超出范围,另一个来自thread-2,它将保留在地图中并提供给所有未来请求者。
答案 5 :(得分:0)
我不确定这一点,但如果你有代码,迭代“fullMap”,AFAIK你可能会被抛出一种“Concurent Modification Exception”。这不能在您的代码中,但可能发生在SoftMap的库例程中。 这可能会导致您的代码在运行时偶尔断开,没有明显的原因,并且没有一个好的方法来处理这种情况。
只是一种复杂的说法:“如有疑问,请小心”。 顺便说一句:不要先考虑当今计算机的性能。
快乐黑客
Huibert Gill