Как обнаружить нарушения синхронизации с Java - PullRequest
9 голосов
/ 18 ноября 2008

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

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

Я жажду чего-то подобного, что можно сделать для потока рассылки AWT со следующим:

public static void checkDispatchThread() {
    if(!SwingUtilities.isEventDispatchThread()) {
        throw new RuntimeException("GUI change made outside AWT dispatch thread");
    }
}

Я бы только хотел что-то более общее. Описание проблемы не очень понятно, но я надеюсь, что у кого-то есть хорошие подходы =)

Ответы [ 9 ]

2 голосов
/ 18 ноября 2008

Когда возникает проблема с потоками в Java, она обычно связана с обнаружением взаимоблокировки, а не просто с отслеживанием того, какие потоки одновременно получают доступ к синхронизированному разделу. Расширение JMX , добавленное в JRE начиная с версии 1.5, может помочь вам обнаружить эти тупики. Фактически мы используем JMX внутри нашего собственного программного обеспечения, чтобы автоматически обнаруживать тупики трассировки, где она была найдена.

Вот пример о том, как его использовать.

2 голосов
/ 18 ноября 2008

IntelliJ IDEA имеет много полезного параллелизма проверок . Например, он предупреждает вас, когда вы обращаетесь к одному и тому же объекту как из синхронизированного, так и из несинхронизированного контекста, когда вы синхронизируете неконечные объекты и т. Д.

Аналогично, FindBugs имеет много похожих проверок .

2 голосов
/ 18 ноября 2008

Вы ищете Святой Грааль, я думаю. AFAIK его не существует, и Java не является языком, который позволяет легко создать такой подход.

«Параллелизм Java на практике» содержит раздел о тестировании на проблемы с многопоточностью. Он обращает особое внимание на то, как трудно это сделать.

1 голос
/ 18 ноября 2008

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

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

class Foo {

  private final Thread owner = Thread.currentThread();

  void x() {
    assert Thread.currentThread() == owner;
    /* Implement method. */
  }

}

Ссылка на владельца все еще заполняется, даже когда утверждения отключены, поэтому она не является полностью «бесплатной». Я также не хотел бы загромождать многие мои уроки этим образцом.

Вам также может пригодиться метод Thread.holdsLock (Object) .

1 голос
/ 18 ноября 2008

Возможно, вас заинтересует подход, о котором писал Питер Вентжер, который он называет Детектор параллелизма . Я не верю, что он все еще использовал его с открытым исходным кодом, но, поскольку он описывает это, основная идея состоит в том, чтобы использовать AOP для инструментирования кода, который вы заинтересованы в профилировании, и записывать, какой поток коснулся какого поля. После этого нужно вручную или автоматически проанализировать сгенерированные журналы.

1 голос
/ 18 ноября 2008

Попробуйте ConTest или Скрытность

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

Также проверьте этот вопрос: Модульное тестирование многопоточного приложения?

1 голос
/ 18 ноября 2008

Помимо упоминания @ Fernando о взаимоблокировке потоков, еще одна проблема с несколькими потоками заключается в одновременных модификациях и проблемах, которые это может вызвать.

Одна вещь, которую Java делает внутренне, заключается в том, что класс коллекции хранит счет того, сколько раз он обновлялся. И затем итератор проверяет это значение в каждом .next () по сравнению с тем, что было при создании интегратора, чтобы увидеть, обновлялась ли коллекция во время итерации. Я думаю, что этот принцип можно было бы использовать более широко.

0 голосов
/ 18 ноября 2008

Вы можете использовать Профилировщик Netbeans или JConsole для глубокой проверки состояния потоков

0 голосов
/ 18 ноября 2008

Для приведенного вами конкретного примера SwingLabs имеет некоторый вспомогательный код для обнаружения нарушений потока событий и зависаний. https://swinghelper.dev.java.net/

Некоторое время назад я работал с инструментами профилирования java JProbe. Один из их инструментов (threadalyzer?) Искал нарушения синхронизации потоков. Глядя на их веб-страницу, я не вижу инструмент с таким названием или совсем то, что я помню. Но вы можете посмотреть. http://www.quest.com/jprobe/performance-home.aspx

...