同步对象并更改其字段之一

时间:2018-09-11 08:16:04

标签: java multithreading synchronization locking

我试图理解一部分代码,其中涉及在对象上进行同步,并且其中一个同步块更改了该对象的某些字段。我正在查看的代码类似于以下内容:

public class ClassA {
    private ClassB someObject = new ClassB();

    public void FuncA() {
        synchronized(someObject) {
            //change some field of someObject
        }
    }

    public void FuncB() {
        synchronized(someObject) {
            //change some field of someObject
        }
    }
}

这是安全的做法吗?我已经在线阅读了几页描述锁的安全操作的页面,但似乎没有一个能处理类似的例子。

感谢您的帮助。谢谢!

3 个答案:

答案 0 :(得分:1)

是的,很好。

例如,这基本上是您从多个线程写入ArrayList时可以执行的操作:您在列表上进行了同步,并更新了其字段(内部数组,大小等)。

注意事项是,您也不得在任何地方以非同步方式访问someObject

public class ClassA {
    private ClassB someObject = new ClassB();

    public void FuncA() {
        synchronized(someObject) {
            //change some field of someObject
        }
    }

    // ...

    // BAD! Don't do this.
    public void FuncC() {
        // read some field of someObject
    }
}

答案 1 :(得分:1)

您可以通过多种方式来同步对方法的访问。
根据同步要求,一个看起来比另一个更好。

  

这是安全的做法吗?

如果将它用于适合的用例,这是一种安全的做法。
在这里,同步很有意义,因为它锁定了someObject,这两个方法对它们进行了修改。
是的,您可以在this上进行同步,也可以同步整个方法,例如:

public class ClassA {
    private ClassB someObject = new ClassB();

    public void FuncA() {
        synchronized(this) {
            //change some field of someObject
        }
    }

    public void FuncB() {
        synchronized(this) {
            //change some field of someObject
        }
    }
}

,但是这些将锁定整个对象,而这可能不是必需的。

答案 2 :(得分:1)

是的,这很安全。 someObject是私有的,因此只有FuncAFuncB可以访问它。它们都在someObject上同步,因此即使来自不同的运行线程,一次也只能在someObject上执行一种方法。

请注意,重要的是,ClassA的所有要访问someObject的方法都应在synchronized的{​​{1}}内这样做,以免出现读写不一致的风险声明为someObject(除非您确切地了解自己在做什么!)。