我需要锁吗?

时间:2014-04-15 06:33:37

标签: java concurrency

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

之前锁定(或将方法声明为已同步) 有人认为我不需要锁定,因为在Java中,赋值操作(例如myObj = newObj;)是原子的。但是我得不到的是myObj.getSomething();这不是原子操作,而是O(n ^ 2)所以我认为仍然需要锁定。它是否正确?

提前致谢。

5 个答案:

答案 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()使用共享的可变值,则它必须是同步方法。