Java 在这种情况下,同步块能帮我吗?

Java 在这种情况下,同步块能帮我吗?,java,android,multithreading,Java,Android,Multithreading,application.temporaryStory是全局可见的Story对象,至少有2个线程可以对其进行写入和读取 在适配器中,我有以下代码 synchronized (this){ if(application.temporaryStory!=null){ // Line A application.temporaryStory.setLastImageViewed(position); // Line B

application.temporaryStory
是全局可见的
Story
对象,至少有2个线程可以对其进行写入和读取

在适配器中,我有以下代码

        synchronized (this){
            if(application.temporaryStory!=null){ // Line A
                application.temporaryStory.setLastImageViewed(position); // Line B
            }
        }
此代码在主线程中执行。
尽管存在同步块,工作线程是否可能将签入行a和签入行B中的代码之间的
应用程序.temporaryStory
对象清空?

您需要同步对同一监视器对象上的对象的所有读写操作。否则,在当前线程运行时,其他线程可能会更改该值。因此我建议在这里使用
应用程序
,因为它似乎是
临时故事
的“所有者”:

synchronized (this){
    if(application.temporaryStory!=null){
        application.temporaryStory.setLastImageViewed(position);
    }
}
如果将
temporaryStory
封装到某个地方(例如,在应用程序中,但可能有更好的地方),则效果会更好,因此只能通过同步方法访问

但要做到这一点,您需要将需要以原子方式访问
temporaryStory
的所有代码移动到封装类中。因此,示例中的代码需要移动到应用程序类:

public synchronized void setLastImageViewed(...) {
    if(application.temporaryStory!=null){ // Line A
        application.temporaryStory.setLastImageViewed(position);
    }
}

这段代码可能适合也可能不适合您现有的应用程序类。如果您觉得它不适合这里,请创建一个新类和一个新对象,以提供对临时故事的访问。使用这个新类来同步对临时story对象的所有访问。

是的,这是可能的:由于该块是外部同步的,不同步的调用足以使其失败

这一切的根本原因是公开了成员变量。良好的编程实践鼓励所有变量都是私有的,并在必要时通过公共方法公开它们

更新

因此,如果不是公共变量
temporaryStore
,而是为每个需要原子化的操作提供一个公共方法,则可以在这些方法中引入内部同步,从而保护对
temporaryStore
对象的所有可能访问

在您的情况下,您需要:

public void setLastImageViewed(position)
{
   synchronized (this){
        if(application.temporaryStory!=null){ // Line A
            application.temporaryStory.setLastImageViewed(position); // Line B
        }
    }
}

如果改用
AtomicReference
,则无需显式同步即可:

public final AtomicReference<Story> temporaryStoryHolder = new AtomicReference<>();

如果工作线程与执行A/B行的线程不在同一对象上同步,则为“是”。所有对temporaryStory的访问必须与同一对象同步!我是否可以将每个读/写操作同步到application.temporaryStory本身?我认为这应该是可能的!我可以将临时Story对象包装到另一个对象中,该对象同步所有读/写操作吗?@J.K.是的,我刚刚更新了答案。将在一分钟内添加更多详细信息;)所以,如果我有在同步块中返回故事的getTemporaryStory和在同步块中设置故事的setTemporaryStory,我就没有问题了?这不是完全正确的。getTemporaryStore方法对读取后更新问题没有帮助。您需要将所有需要以原子方式运行的代码移动到封装temporaryStory的类中。@LittleSanti取消了我的反对票,因为现在您的答案是正确的:)@David Tanzer非常感谢。你一开始投了很好的反对票。:-)
Story temporaryStory = temporaryStoryHolder.get();
if (temporaryStory != null) {
  temporaryStory.setLastImageViewed(position);
}