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);
}