您能否安全地对Java方法参数进行同步?

您能否安全地对Java方法参数进行同步?,java,methods,parameters,locking,synchronized,Java,Methods,Parameters,Locking,Synchronized,以这个代码为例: 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 vari

以这个代码为例:

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”是否可以通过传递其lock var重新编写以使用HelperClass,从而使所有内容仍然是线程安全的?i、 e

public void myMethod() {
    _helperObject.helperMethod(_lock, _mutableObject);
}

我不确定这一点,因为Java将按值传递lockVar,并且每个线程将获得一个单独的lockVar副本(即使每个副本指向堆上的同一个对象)。我想问题可以归结为“synchronized”关键字是如何工作的——它是锁定变量还是锁定变量引用的堆上的值?

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

变量/成员[有时]包含对象,而在
synchronized(x)
中实际同步的是[variable]
x
中包含的结果对象

变量的线程可见性还存在一些其他问题(例如,可能从变量中读取“过时”对象),但这在这里不适用:没有重新分配
\u lock
,初始(“最终”)分配的可见性得到保证。因此,在这种情况下,可以保证method参数始终包含用于同步的正确(相同)对象

但是,如果所使用的锁对象(假定
\u lock
不是最终的)发生更改,则需要重新评估适当的值/线程可见性,但其他方面与任何跨线程访问都没有区别


愉快的编码。

事实上,我的示例并不正确。我不是想把可变对象标记为最终对象。我认为如果父对象中的_mumutableobject是非final的,那么这个锁定就不起作用。如果将该值作为变量传递给helper方法,然后将_mutableObject更改为指向父类中的其他对象,那么当helper方法运行时,它不再保持对_mutableObject的正确引用。锁仍将锁定,但您将“保护”过时的_mutableObject值。这正是我的问题应该指出的。我会接受你的答案,假设只有当_mutableObject在父类中是“final”时,这才有效。无论使用我的示例的哪个版本,_lock对象始终需要声明为final。事实上,我不应该创建包含“可变”对象的示例。我应该描述一下,我想保护一个非最终变量,称之为“private Object\u Object”。我想要锁来保护这个值。如果将示例更改为该示例,我认为您不能将锁定传递给帮助器方法,因为帮助器方法会变得过时_objectreference.@Android Dev用于锁定对象的对象对于所需的每个互斥同步都应该是稳定和唯一的。受同步保护的变量(或对象)可能会更改(同步上下文将确保内存障碍,只要所有此类同步都在同一个锁对象上运行,就会在保证之前发生)。交换用于锁的对象通常不是一个好主意(锁对象可以被改变,这不会影响它与
synchronized
的使用——重要的是相同的对象用于同步。)我没有交换用于锁的对象。我正在用锁交换我要保护的对象。我理解您所说的锁对象(不是变量)上发生的同步。但是,如果我试图通过使用锁来保护实例变量,我不认为我可以编写一个helper方法并传入该变量(使用锁,我可以传入该变量),因为只要我将变量作为参数传入,它就可以被另一个线程更改。在传递到helper方法之前,我需要对锁进行同步。这就是我需要解决的问题。