Java同步-这个简单的方法需要它吗?

Java同步-这个简单的方法需要它吗?,java,synchronization,methods,Java,Synchronization,Methods,我有一个从多个线程调用的简单方法 @Override public Bitmap getFullBitmap(Filter f, ProgressCallback<String> pc) { // Requires synchronisation? Bitmap bitmap = fullMap.get(f.id); if(bitmap == null){ f.setProgressCallback(pc); bitmap =

我有一个从多个线程调用的简单方法

@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;
}
@覆盖
公共位图getFullBitmap(过滤器f,pc){
//需要同步吗?
位图位图=fullMap.get(f.id);
如果(位图==null){
f、 setProgressCallback(pc);
位图=f.e.evaluate(当前位图);
fullMap.put(f.id,位图);
}
返回位图;
}
由于所使用的对象都不是该类的字段(除了fullMap),因此仅调用该类可以吗?或者,例如,当方法执行时,一个线程是否可以更改位图的值

fullMap是一个SoftHashMap,它维护索引的位图对象的软引用,但用于创建它的筛选器id除外。如果这有意义的话

我没有遇到任何问题,但我想我可能需要它

如果这不清楚,请要求澄清,这个问题在我脑海中是有意义的;)

编辑

  • currentBitmap是Bitmap类型的对象,系统中有一个位图被视为当前位图,由此类管理
  • 这段代码形成了一个非常基本的缓存, 返回的位图将始终为空 每个id都相同,但不相同 在该方法之外进行了修改
  • 通过在 描述的SoftHashMap和一个硬文件的FIFO队列 最近10次的参考文献 我希望避免打昂贵的电话 进行f.e.评估。话虽如此 呼叫f.e.evaluate将返回一个 相同的位图对象(如果是) 给定相同的输入。过了一会儿 我觉得好像 这个方法是个好主意,因为它什么都没有 正数来自两个线程 为相同的目标执行此代码 过滤器
  • 此外,我做了位图最终作为它 不应该在创造后变异
非常感谢!
Gav

如果您的方法只使用传入的参数和局部变量,没有共享状态,那么我认为它是线程安全的,不需要同步


线程安全必须考虑可变的共享状态。fullmap是该对象状态的一部分吗?如果是,则必须同步其访问。

2个线程可以同时访问map
fullMap
。两者都可以确定映射不包含同一个键的值,各自创建一个值,然后将其写回,从而插入一个键两次

这可能不仅仅是一个效率问题。但是,这可能会引起混淆,并可能在将来随着解决方案的发展而导致问题(将来创建这些对象的成本有多高?如果有人将代码复制/粘贴到不太合适的地方会发生什么情况!)


我强烈建议在上面进行同步(最有可能是在
fullMap
本身而不是包含对象上进行同步,但在决定所需内容之前,更多的上下文将非常有用)

SoftHashMap.put本身可能不是线程安全的。SoftHashMap不在标准库中,但在标准库中,并且它不同步。除了同步映射上的方法外,您可能还希望使用以确保其他方法不会同时修改映射。

如果返回的位图在方法之外修改,我将选择同步路径。当f.id处的位图为空时,您可能会有两个线程访问上述方法,这两个线程创建了一个位图并将其添加到映射中,而第二个将覆盖映射中的第一个。现在您有两个,一个将由thread-1修改,但在thread-1完成其处理后将超出范围,另一个来自thread-2,它将保留在映射中并提供给所有未来的请求者

您绝对需要同步,因为您可以让两个线程决定
f.id
不在映射中,构造并添加一个。每个线程将返回一个不同的
f.id
实例,即使映射只包含最后完成的实例

问题不在于变量
位图
。这是线程安全的,因为它是单个线程的本地。但是,对`fullMap(我假定它是类的一个字段)的访问需要同步,因为您正在执行“如果不存在则放置”的操作


假设构造位图的成本很高,最好的方法就是同步方法
getFullBitmap()
。如果构建成本非常低——比同步成本更低——那么我建议总是构建新对象并在一个平台上进行。但是,当构建对象的成本很高时,这是一个坏主意。

我不确定这一点,但是如果您有代码,那么可能会抛出一种“Concurent Modification Exception”,在“fullMap”上迭代。这不能出现在代码中,但可能发生在SoftMap的库例程中。 这可能会导致您的代码在运行时时不时地被破坏,没有明显的原因,也没有一个好的方法来处理这种情况

这只是一种复杂的说法:“如果有疑问,请小心”。 顺便说一句:对于今天的计算机,不要先考虑性能

快乐黑客


Huibert Gill

指令重新排序并不是您所说的竞争条件的来源。这是一个简单的多线程争用条件。我认为双重检查锁定问题不适用于这里,因为位图不是字段。当对象进入映射时,它应该被正确构造。此外,如果出于某种原因只需要第一个键值对的值,那么向映射添加两次键应该是一个问题。否则,第二个值将覆盖第一个值。不过,我认为您关于在地图上同步的想法可能是对的,因为put本身可能不是线程安全的。@Matthew-编辑以反映在效率之外插入两次密钥可能不是问题。我已进一步编辑以删除对DCL的引用。你是对的,它只适用于