MyObject myObj ...
public void updateObj(){
MyObject newObj = getNewMyObject();
myObj = newObj;
}
public int getSomething(){
//O(n^2) operation performed in getSomething method
int something = myObj.getSomething();
return something;
}
假设主线程经常调用updateObj()
和子线程调用getSomething()
方法。
我需要在myObj = newObj;
和int something = myObj.getSomething();
myObj = newObj;
)是原子的。但是我得不到的是myObj.getSomething();
这不是原子操作,而是O(n ^ 2)所以我认为仍然需要锁定。它是否正确?
提前致谢。
答案 0 :(得分:3)
您需要声明myObject volatile,否则getSomething()方法可能看不到更新的对象。除此之外,我在上面的代码中看不到任何同步问题
答案 1 :(得分:2)
是的,您必须正确同步对共享变量的访问权限。根据{{3}},您的代码在所有可能的执行中都不保证读取和写入之间的Java Memory Model关系。
正确的同步并不总是意味着使用锁;在你的情况下,将myObj声明为volatile可以完成这项任务(假设你在构造之后不会改变它)。
答案 2 :(得分:1)
对引用变量的写入确实是原子的。
但是没有锁定(或其他类型的同步),其他线程无法保证将myObj
的更新值看到极端,只能看到它的初始值(null
,如果你没有在构造函数中分配它。)
你将很难以这样的方式编写一个程序,它正好表现出这种极端的行为,但是如果没有同步,当线程调用updateObj
并且某些其他线程调用时,你肯定会得到不一致的结果{ {1}}并使用过时的getSomething
实例。
确保myObj
使用最新getSomething
的最简单方法是将myObj
声明为myObj
。
答案 3 :(得分:0)
是的,你需要一些锁定。因为我可以看到两个不同的函数被不同的线程调用,并且你在myObj
方法中使用getSomething()
。
现在假设您的子线程正在执行getSomething()
并且同时您的主线程已更改myObj
,那么您的程序将成为竞争条件的受害者,并且您可能无法获得所需的输出。
但是,这取决于你写的整个程序。希望这有帮助
答案 4 :(得分:0)
需要同步updateObj()
,以便以原子方式写入共享的可变myObj
。
MyObjects.getSomething()
使用共享的可变值,则它必须是同步方法。