Синхронизация на объекте и изменение одного из его полей - PullRequest
0 голосов
/ 11 сентября 2018

Я пытаюсь понять часть кода, которая включает синхронизацию на объекте, и один из синхронизированных блоков изменяет некоторые поля объекта. Код, на который я смотрю, похож на следующий:

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 голосов
/ 11 сентября 2018

У вас есть несколько способов синхронизации доступа к методу.
Один выглядит лучше другого в соответствии с требованием синхронизации.

Это безопасная практика?

Это безопасная практика, если она используется для подходящего варианта использования.
Здесь синхронизация имеет смысл, поскольку она блокирует 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
        }
    }
}

но они могут заблокировать весь объект, хотя это может и не потребоваться.

0 голосов
/ 11 сентября 2018

Да, это безопасно. someObject является приватным, поэтому только FuncA и FuncB имеют к нему доступ. Они оба синхронизируются на someObject, поэтому только один из методов одновременно будет выполняться на someObject, даже если из разных запущенных потоков.

Обратите внимание, что важно, чтобы все методы ClassA, которые хотят получить доступ к someObject, делали это в пределах synchronized на someObject, чтобы избежать любого риска чтения или записи несовместимого состояния в someObject (если вы не точно понимаю, что ты делаешь!).

0 голосов
/ 11 сентября 2018

Да, все в порядке.

Например, это в основном то, что вы (можете) делать при записи в 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
    }
}
...