Другие ответили на ваш прямой вопрос.
Я хотел бы прояснить что-то, что может быть неправильным представлением с вашей стороны ... и если это так, то это опасный один.
Метод m НЕ синхронизирован, и в этом нет необходимости, поскольку он действительно не меняет состояние объекта x типа X.
Это не достаточное условие.Методы, которые не меняют состояние, как правило, тоже должны быть синхронизированы.
Предположим, у вас есть класс Test с простым геттером и сеттером:
public class Test {
private int foo;
public int getFoo() {
return foo;
}
public synchronized void setFoo(int foo) {
this.foo = foo;
}
}
Является ли геттер потокобезопасным?
- По вашему правилу да.
- На самом деле нет.
Почему?Поскольку, если потоки, которые вызывают getFoo
и setFoo
, не синхронизируются должным образом, вызов getFoo()
после вызова setFoo(...)
может увидеть устаревшее значение для foo
.
Это один из технеприятные случаи, когда вам сойдет с рук почти все время.Но очень редко время двух вызовов будет таким, что ошибка кусает вас.Этот тип ошибки, вероятно, проскользнет сквозь трещины вашего тестирования, и его будет очень трудно воспроизвести, когда он возникнет на производстве.
Единственный случай, когда абсолютно безопасно дляДоступ к состоянию объекта из нескольких потоков без синхронизации происходит, когда состояние объявляется как final
, а конструктор не публикует объект.