你能安全地同步Java方法参数吗?

时间:2011-06-02 02:06:49

标签: 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 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)
        }
    }
}

可以通过传递其锁定var来重写“myMethod”以使用HelperClass,以便一切仍然是线程安全的吗?即,

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

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

1 个答案:

答案 0 :(得分:9)

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

变量/成员[有时]包含对象,它是[变量] x中包含的生成的对象,它实际上在{{1}中同步}}

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

但是,如果使用的锁定对象(可能_lock不是最终的)发生了更改,则需要重新评估相应的值/线程可见性,但不会与任何跨线程访问不同

快乐的编码。