java - 我是否应该创建虚拟对象以便能够同步可能为空的属性?

标签 java multithreading

假设您有一个代表延迟加载图像的类。这意味着它仅在需要时加载图像,然后缓存它:

public class LazyImage {
  //Path souldn't ever change
  public final File path;
  //This will be filled when the image is loaded
  private Image image = null;
  public LazyImage(File path) {
    //I ommited some safety checks chere, like null check and existence check.
    this.path = path;
  }

  public Image getImage() {
    if(image!=null)
      return image;
    try {
      image = ImageIO.read(path);
    }
    catch(IOException e) {
      //Here, the class should remember that there was a problem getting the image
      // and probably not try again, based on the exception type
    }
  }
}

如果您在更复杂的应用程序中使用此类,您很快就会发现需要使其线程安全,以便不会有多个线程调用 image = ImageIO.read(path);同时。在这种特殊情况下,您希望像这样进行同步:

  public final String imageMutex = "Prevents the image property from being modified multiple times.";
  public Image getImage() {
    if(image!=null)
      return image;
    //This only executes if the image was nullptr right now
    synchronized(imageMutex) {
      //If was blocked, check for the null once again
      //most likely will not be null any more
      if(image==null) {
        File file = new File(path);
        try {
          image = ImageIO.read(file);
        }
        catch(IOException e) {
          image=null;
          image_failed = true;
        }
      }
    }
    return image;
  }

我实际上并不完全确定非同步的安全性 if在该方法的开头是。但这个问题是关于imageMutex多变的。我无法在 image 上同步因为一开始它就是空的。我也不想在 getImage 上同步方法,因为即使线程只是在读取图像,它也会阻塞线程。

那么程序员如何同步变量,而不是特定的对象或方法?

最佳答案

事实上,你就是这么做的!

大多数时候,互斥锁(在这种类型的上下文中通常又称为“守卫”)只是 Object imageLock = new Object (),但除此之外,您的理解是正确的。

但是,对于此方案,您的 image 字段需要是 volatile 的 - 称为 double checked lock ——去工作。

关于java - 我是否应该创建虚拟对象以便能够同步可能为空的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30015198/

相关文章:

multithreading - 在Visual Studio Express 2010中进行调试时如何列出线程

ios - 核心数据对象的顺序改变,核心数据合并后上下文之间不同

java - 如何用while循环填充数组?

Java - 字符串内存泄漏

java - instanceof运算符java的复杂性

java - 确定 Java 程序的确定性线程执行

java - 如何使用serialize Collections.synchronizedList和co

java - 如何在WildFly8.2.0中正确支持servlet

c# - 为什么我们应该避免锁定(this)?

java - 从控制台执行时 System.out.println 不适用于线程