Скорость Синхронизации против Нормальной - PullRequest
1 голос
/ 10 февраля 2011

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

class MyClass implements MyInterface{
//interface implementation methods, not synchronized
}

Но нам также нужна была синхронизированная версия класса.Итак, мы создали класс-оболочку, который реализует тот же интерфейс, но имеет конструктор, который принимает экземпляр MyClass.Любой вызов методов синхронизированного класса делегируется экземпляру MyClass.Вот мой синхронизированный класс ..

class SynchronizedMyClass implements MyInterface{
//the constructor
public SynchronizedMyClass(MyInterface i/*this is actually an instance of MyClass*/)
//interface implementation methods; all synchronized; all delegated to the MyInterface instance
}

После всего этого я провел множество тестовых прогонов с обоими классами.Тесты включают чтение файлов журнала и подсчет URL-адресов в каждой строке.Проблема заключается в том, что синхронизированная версия класса последовательно занимает меньше времени для анализа.Я использую только один поток для теста, так что нет никакой вероятности взаимоблокировок, обхода условий и т. Д. Каждый файл журнала содержит более 5 миллионов строк, что означает вызов методов более 5 миллионов раз.Кто-нибудь может объяснить, почему синхронная версия класса migt занимает меньше времени, чем обычная?

Ответы [ 2 ]

5 голосов
/ 10 февраля 2011

Сначала вы должны прочитать о создании эталонных тестов в Java: Как написать корректный микропроцессорный тест в Java?

Если предположить, что эталон хороший, то вот несколько возможных причин:

  • Разрешение блокировки : Если JVM может заметить, что метод может быть вызван только из одного потока, она может оптимизировать синхронизацию.

  • Укрупнение блокировки : JVM может объединять несколько синхронизированных блоков в один блок, что повышает производительность. Возможно, JVM сможет немного лучше оптимизировать синхронизированную версию метода.

  • Несоответствующие синхронизированные блоки в Java работают быстро, поэтому может быть трудно заметить разницу (хотя в любом случае должны быть некоторые накладные расходы), а причина разницы в производительности может быть вызвана чем-то другим. Синхронизированные блоки становятся медленными, когда возникает конфликт (то есть многие потоки пытаются получить к нему доступ одновременно), и в этом случае java.util.concurrent.locks и другие механизмы синхронизации могут быть быстрее.

Причина может быть и в другом. Возможно, JVM оптимизирует методы по-разному. Чтобы увидеть, что на самом деле происходит, посмотрите, какой нативный код генерирует JIT: Как увидеть JIT-скомпилированный код в JVM?

1 голос
/ 10 февраля 2011

Как уже указывалось, микро-бенчмаркинг не так уж тривиален с Java.

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

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

Честно говоря, звучит немного странно, когда требуются как полностью синхронизированные, так и несинхронизированные версии одного и того же класса.

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