[英]Java Synchronisation - Do I need it for this simple method?
我有一个从多个线程调用的简单方法;
@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,但该索引用于创建它。 如果那有意义的话。
我没有任何问题,但我认为我可能需要它。
如果不清楚,请要求澄清,这个问题在我看来很有意义;)
编辑
非常感谢! 加夫
2个线程可以同时访问地图fullMap
。 两者都可以确定该映射不包含相同键的值,每个都创建一个,然后将其写回,从而将键插入两次。
这可能不是效率以外的问题。 但是,这可能会引起混乱,并且可能随着解决方案的发展而在将来引起问题(将来创建这些对象的成本将是多少?如果有人将代码复制/粘贴到不合适的地方会发生什么!)
我强烈建议在上面进行同步(最有可能在fullMap
本身而不是在包含对象上进行同步,但是在确定确切需要什么之前,更多上下文将很有用)
SoftHashMap.put本身可能不是线程安全的。 SoftHashMap不在标准库中,但是WeakHashMap在,并且不同步。 除了在地图上同步方法外,您可能还想使用Collections.synchronizedMap来确保其他方法不会同时修改地图。
您绝对需要同步,因为您可以有两个线程来确定f.id
不在映射中,然后构造并添加一个。 每个线程将返回f.id
的不同实例,即使该映射仅包含最后完成的那个。
问题不在于变量bitmap
。 这是线程安全的,因为它在单个线程中是本地的。 但是,由于您正在执行“如果不放置”,因此对`fullMap的访问(我认为是类的一个字段)需要进行同步。
假设构造位图的成本很高,那么做到这一点的最佳方法就是同步方法getFullBitmap()
。 如果是非常便宜的构建-比同步便宜-那么我会建议总是构建新的对象和做putIfAbsent
上ConcurrentMap
。 但是,当对象的构造成本很高时,这是个坏主意。
如果您的方法仅使用传入的参数和局部变量,而没有共享状态,那么我想说它是线程安全的,不需要同步。
线程安全必须担心可变的共享状态。 全图是该对象状态的一部分吗? 如果是,则必须同步其访问。
如果返回的位图在方法外部被修改,我将选择同步路径。 您可能会有2个线程访问上述方法的风险,而f.id处的位图为null,同时创建一个线程并将其添加到映射中,而第二个线程将覆盖第一个线程。 现在,您有两个,一个将由线程1修改,但是一旦线程1完成其处理就超出范围,另一个来自线程2,它将保留在映射中并提供给将来使用请求者。
我对此不太确定,但是如果您有代码在“ fullMap”上进行迭代,则AFAIK可能会引发“一致性修改异常”。 这一定不能在您的代码中,但是可能在SoftMap的库例程中发生。 这可能会导致您的代码不时地在运行时中断,没有明显的原因,并且没有很好的方法来处理这种情况。
只是一种复杂的说法:“如有疑问,请小心”。 顺便说一句:不要首先考虑当今计算机的性能。
快乐黑客
休伯特·吉尔
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.