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