假设您有一个代表延迟加载图像的类。这意味着它仅在需要时加载图像,然后缓存它:
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/