您可以安全地同步 Java 方法参数吗?
拿这段代码:
public class MyClass {
private final Object _lock = new Object();
private final MyMutableClass _mutableObject = new MyMutableClass()
public void myMethod() {
synchronized(_lock) { // we are synchronizing on instance variable _lock
// do something with mutableVar
//(i.e. call a "set" method on _mutableObject)
}
}
}
现在,想象一下将 myMethod() 内的代码委托给某个传递锁的帮助程序类,
public class HelperClass {
public helperMethod(Object lockVar, MyMutableClass mutableVar) {
synchronized(lockVar) { // we are now synchronizing on a method param,
// each thread has own copy
// do something with mutableVar
// (i.e. call a "set" method on mutableVar)
}
}
}
可以通过传递其锁变量来重写“myMethod”以使用 HelperClass,以便一切仍然是线程安全的吗?即,
public void myMethod() {
_helperObject.helperMethod(_lock, _mutableObject);
}
我对此不确定,因为Java将按值传递lockVar,并且每个线程将获得lockVar的单独副本(即使每个副本都指向堆上的同一个对象)。我想问题归结为“synchronized”关键字如何工作——它是否锁定变量,或者变量引用的堆上的值?
Take this code:
public class MyClass {
private final Object _lock = new Object();
private final MyMutableClass _mutableObject = new MyMutableClass()
public void myMethod() {
synchronized(_lock) { // we are synchronizing on instance variable _lock
// do something with mutableVar
//(i.e. call a "set" method on _mutableObject)
}
}
}
now, imagine delegating the code inside myMethod() to some helper class where you pass the lock
public class HelperClass {
public helperMethod(Object lockVar, MyMutableClass mutableVar) {
synchronized(lockVar) { // we are now synchronizing on a method param,
// each thread has own copy
// do something with mutableVar
// (i.e. call a "set" method on mutableVar)
}
}
}
can "myMethod" be re-written to use the HelperClass by passing its lock var, so that everything is still thread safe? i.e.,
public void myMethod() {
_helperObject.helperMethod(_lock, _mutableObject);
}
I am not sure about this, because Java will pass the lockVar by value, and every thread will get a separate copy of lockVar (even though each copy points to the same object on the heap). I guess the question comes down to how 'synchronized' keyword works -- does it lock on the variable, or the value on the heap that the variable references?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
同步是在对象上完成的,而不是变量。
变量/成员[有时]包含对象,并且它是结果对象包含在[变量]
x
中,实际上在synchronized(x)
中同步。变量的线程可见性还存在一些其他问题(例如,可能从变量中读取“陈旧”对象),但这不适用于此处:没有重新分配
_lock
并且保证初始(“最终”)分配的可见性。因此,在这种情况下,可以保证方法参数始终包含用于同步的正确(相同)对象。但是,如果使用的锁定对象(大概
_lock
不是最终的)发生变化,则需要重新评估适当的值/线程可见性,但在其他方面与任何跨线程访问没有区别。快乐编码。
Synchronization is done upon objects, not variables.
Variables/members [sometimes] contain objects and it is the resulting object contained in [variable]
x
that is actually synchronized upon insynchronized(x)
.There are a few other issues with thread-visibility of variables (e.g. might read a "stale" object from a variable), but that does not apply here: there is no re-assignment of
_lock
and the visibility of the initial ("final") assignment is guaranteed. Because of this it is guaranteed that, in this case, the method parameter will always contain the correct (same) object used for the synchronization.If the lock object used (where presumably
_lock
is not final) changes, however, then that would require re-evaluation of the appropriate values/thread-visibility but otherwise does not differ from any cross-thread access.Happy coding.