您可以安全地同步 Java 方法参数吗?

发布于 2024-11-11 21:35:25 字数 1140 浏览 6 评论 0原文

拿这段代码:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ぃ弥猫深巷。 2024-11-18 21:35:25

同步是在对象上完成的,而不是变量

变量/成员[有时]包含对象,并且它是结果对象包含在[变量]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 in synchronized(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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文