Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我应该创建虚拟对象以便能够在可能为null的属性上进行同步吗?_Java_Multithreading - Fatal编程技术网

Java 我应该创建虚拟对象以便能够在可能为null的属性上进行同步吗?

Java 我应该创建虚拟对象以便能够在可能为null的属性上进行同步吗?,java,multithreading,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 so

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

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
变量的。我无法同步
图像
,因为它在开始时为空。我也不想在
getImage
方法上进行同步,因为它会阻止线程,即使它们只是在读取图像


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

事实上,基本上就是这样做的

大多数情况下,互斥锁(在这种类型的上下文中通常也称为“guard”)只是
Object imageLock=new Object()
,但在其他方面,您已经做对了


您的
图像
字段必须是可变的,但是,要使此方案(称为a)起作用。

为什么不在
上同步?@realpoint如果有两个变量要同步呢?变量A会阻止变量B。如果你有两个独立的状态变量,当然可以。但是如果只有一个状态变量,或者状态变量总是一起操作,那么
这是一个很好的选择。你的
lazymeage
有可能会有如此复杂的状态吗?@realpointist
lazymeage
只是这个问题的概貌。real类还缓存大小调整后的图像,并清除将不再使用的图像。。。在此基础上进行同步将使不同的操作相互阻塞。在这个问题上,我在寻找一些通用的解决方案。在简单的类中,您确实可以在
上同步此
,但我不推荐这样做。如果另一个类将您的类用作属性并在其上进行同步,则您可能会遇到问题。根据,每次访问该类时,都会阻塞易失性变量。这是真的吗?我认为重要的是要强调为什么使用文本字符串作为锁是个坏主意:因为内部操作,所有
lazymeage
对象共享的对象都是同一个对象。是的,@realpoinsist说的。:)