Сколько потоков может одновременно вызывать несинхронизированный метод объекта? - PullRequest
1 голос
/ 17 августа 2011

Итак, допустим, у меня есть класс X с методом m. Метод m синхронизирован NOT , и в этом нет необходимости, поскольку он на самом деле не меняет состояние объекта x типа X.

В некоторых потоках я вызываю метод следующим образом: x.m (). Все эти потоки используют один и тот же объект x.

На сколько потоков этот метод (метод m) может быть вызван одновременно для объекта x? Может быть тот факт, что метод вызывается, скажем, 100 нитями, является узким местом для моего приложения?

спасибо.

Ответы [ 5 ]

3 голосов
/ 17 августа 2011

Другие ответили на ваш прямой вопрос.

Я хотел бы прояснить что-то, что может быть неправильным представлением с вашей стороны ... и если это так, то это опасный один.

Метод 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, а конструктор не публикует объект.

3 голосов
/ 17 августа 2011

Если у вас больше потоков в рабочем состоянии, чем у физических ядер, вы в конечном итоге будете тратить время на переключение контекста ... но это все. Тот факт, что эти потоки выполняют один и тот же метод, не имеет значения, если между ними нет координации.

1 голос
/ 17 августа 2011

Да, несинхронизированный метод не заботится о том, сколько потоков его вызывает. Это чисто пассивная сущность, и ничего особенного не происходит, когда в нее входит новый поток.

Возможно, одна вещь, которая смущает некоторых людей, это "автоматическое" хранение, используемое методом. Это хранилище размещается в стеке потока и не требует активного участия метода. Код метода просто получает указатель на хранилище.

(Много, много лет назад этого не произошло. Либо «авто» хранилище было выделено из кучи при вызове метода, либо метод поддерживал список «авто» областей хранения. Но эта парадигма, возможно, исчезла 40 лет назад, и я сомневаюсь, что существует какая-либо система, которая все еще использует ее. И я уверен, что ни одна JVM не использует эту схему.)

1 голос
/ 17 августа 2011

Запомните разницу между потоками и экземплярами. Один выполняет другой, это данные. Если данные не находятся под каким-либо механизмом блокировки или некоторыми ограничениями ресурсов, доступ ограничивается только количеством потоков, которые могут выполняться базовой инфраструктурой. Это ограничение системы (реализация jvm + ОС + машина).

0 голосов
/ 17 августа 2011

У вас будет узкое место, если один поток получит ресурс, который нужен другим, и удержит его для длительной операции.Если это не так для вашего метода, я не вижу, как вы будете испытывать бутылку.

Это теоретический вопрос, или вы наблюдаете поведение в реальном приложении, которое работает медленнее, чемВы думаете, что это должно быть?

Лучший ответ - получить данные и посмотреть.Запустите тест и следите за ним.Будь ученым.

...