Вопрос

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

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

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

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

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

Это было полезно?

Решение

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

class Foo {

  private final Thread owner = Thread.currentThread();

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

}

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

Thread.holdsLock (Object) также может быть полезен для вас.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top