Какова самая частая проблема параллелизма, с которой Вы встретились в Java? [закрытый]

190
задан 5 revs, 3 users 75% 5 August 2012 в 12:49
поделиться

47 ответов

Не понимание java.awt.EventQueue.invokeAndWait действия, как будто это содержит блокировку (эксклюзивный доступ к Потоку Отправки События, EDT). Большая вещь о мертвых блокировках состоит в том, что, даже если это редко происходит, можно захватить отслеживание стека с jstack и т.п. Я видел это во многих широко используемых программах (фиксация к проблеме, которую я только видел, происходят, как только в Netbeans должен быть включен в следующий выпуск).

3
ответ дан 2 revs 23 November 2019 в 05:35
поделиться

Стартовый RMI Java заставляет фоновую задачу работать, который вынуждает сборщик "мусора" работать каждые 60 секунд. Сам по себе это может быть хорошей вещью, однако может случиться так, что сервер RMI не был запущен Вами непосредственно, но платформой/инструментом Вы используете (например, JRun). И, RMI не мог бы на самом деле использоваться ни для чего.

конечным результатом является System.gc () вызов однажды минута. В в большой степени загруженной системе Вы будете видеть следующий вывод в своих журналах - 60 секунд действия, сопровождаемого длинной паузой gc, сопровождаемой на 60 секунд действия, сопровождаемого длинной паузой gc. Это является фатальным для пропускной способности.

решение состоит в том, чтобы выключить явный gc, использующий-XX: + DisableExplicitGC

3
ответ дан JodaStephen 23 November 2019 в 05:35
поделиться

Условия состязания во время объекта завершать/выпускать/завершать работу/деструктор метод и нормальные вызовы.

От Java, я делаю большую интеграцию с ресурсами, которые должны быть закрыты, такие как COM-объекты или Flash player. Разработчики всегда забывают делать, это правильно и заканчивать тем, что имело поток называет объект, который был завершением работы.

2
ответ дан Jen S. 23 November 2019 в 05:35
поделиться

Отказ предоставить ясно определенные методы жизненного цикла на объектах, которые управляют продолжительными потоками. Мне нравится создавать пар методов, названных init () и уничтожать (). Также важно на самом деле звонить, уничтожают (), таким образом, Ваше приложение может выйти корректно.

2
ответ дан Eric Burke 23 November 2019 в 05:35
поделиться

Поддержание занятости всех потоков.

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

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

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

2
ответ дан Ben Manes 23 November 2019 в 05:35
поделиться

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

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

public class UserService {

    private String userName;

    public String getUserName() {
        return userName;
    }

    public void login(String name) {
        this.userName = name; 
        doLogin();
    }

    private void doLogin() {
        userDao.login(getUserName());
    }

    public void delete(String name) {
        this.userName = name; 
        doDelete();
    }

    private void doDelete() {
        userDao.delete(getUserName());
    }

}

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

2
ответ дан Dov Wasserman 23 November 2019 в 05:35
поделиться

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

я пытался использовать, ожидают () и notifyAll () методы, и вот то, как я использовал и упал в аду.

Thread1

Object o1 = new Object();

synchronized(o1) {
    o1.wait();
}

И в другом потоке. Поток - 2

Object o2 = new Object();

synchronized(o2) {
    o2.notifyAll();
}

Thread1 будет ожидать на o1 и Thread2, который должен был вызвать o1.notifyAll (), вызов o2.notifyAll (). Поток 1 никогда не будет просыпаться.

И offcourse типичная проблема не вызова ожидает () или notifyAll () в синхронизируемых блоках и не вызове их использующий тот же объект, который привык к sycnhronze блок.

Object o2 = new Object();

synchronized(o2) {
    notifyAll();
}

Это вызовет IllegalMonitorStateException, так как поток, который вызвал notifyAll () вызвал notifyAll () использующий этот объект, но не является владельцем этого объекта блокирования. Но текущий поток является владельцем o2 объекта блокирования.

2
ответ дан 3 revs, 2 users 79%Deepak Jain 23 November 2019 в 05:35
поделиться

1) частая ошибка, с которой я встретился, включает итерацию по синхронизируемому классу Набора. Это требуется, чтобы, вручную синхронизировался прежде, чем получить итератор и при итерации.

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

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

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

5) Используя несколько объектов синхронизации должен быть тщательно обработан.

3
ответ дан David Nouls 23 November 2019 в 05:35
поделиться

Так как Java 5 там является Thread.getUncaughtExceptionHandler, но этот UncaughtExceptionHandler никогда не называют, когда ExecutorService/ThreadPool используется.
, По крайней мере, я не смог получить UncaughtExceptionHandler с работой ExcutorService.

1
ответ дан Ludwig Wensauer 23 November 2019 в 05:35
поделиться

Я столкнулся с псевдомертвой блокировкой от потока ввода-вывода, который создал фиксатор обратного отсчета. Значительно упрощенная версия проблемы похожа:

public class MyReader implements Runnable {

  private final CountDownLatch done = new CountDownLatch(1);
  private volatile isOkToRun = true;

  public void run() {
    while (isOkToRun) {
       sendMessage(getMessaage());
    }
    done.countDown();
  }

  public void stop() {
    isOkToRun = false;
    done.await();
  }

}

идея остановки () состоит в том, что она не возвратилась, пока поток не вышел, поэтому когда она возвратилась, система была в известном состоянии. Это в порядке, если sendMessage () не приводит к вызову остановки (), где это будет ожидать навсегда. Пока остановка () никогда не вызывается от Выполнимого, все будет работать, как Вы ожидаете. В крупном приложении, однако, действие потока Runnable не может быть очевидным!

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

1
ответ дан Eddie 23 November 2019 в 05:35
поделиться

Помощь с Реализацией Агентов в Функциональном Java и сравнительном тестировании миллионов потоков на многоядерных машинах.

0
ответ дан Tony Morris 23 November 2019 в 05:35
поделиться

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

1
ответ дан Javamann 23 November 2019 в 05:35
поделиться

Мои два цента при том, чтобы стараться избегать проблем синхронизации от запуска — не упускают следующие проблемы/запахи:

  1. При записи кода, всегда знают, в котором потоке Вы находитесь в [1 110].
  2. При разработке класса или API для повторного использования, всегда спрашивают себя, должен ли код быть ориентированным на многопотоковое исполнение . Лучше принять преднамеренное решение и документ, что Ваша единица не ориентирована на многопотоковое исполнение, чем вставить неблагоразумную синхронизацию с потенциалом для мертвой блокировки.
  3. Вызовы new Thread() являются запахом . Используйте выделил ExecutorServices вместо этого, которые вынуждают Вас думать о полном понятии поточной обработки своего приложения (см. 1), и поощрите других следовать за ним.
  4. Знают и используют классы библиотеки (как AtomicBoolean и др. , синхронизировал Наборы, и т.д.). Снова: примите сознательное решение о том, важна ли потокобезопасность в данном контексте, не просто используйте их вслепую.
1
ответ дан Rahel Lüthy 23 November 2019 в 05:35
поделиться
public class ThreadA implements Runnable {
    private volatile SharedObject obj;

    public void run() {
        while (true) {
            obj = new SharedObject();
            obj.setValue("Hallo");
        }
    }

    public SharedObject getObj() {
        return obj;
    }
}

проблема я пытаюсь указать здесь (среди других), то, что сброс SharedObject obj происходит прежде, чем установить значение "Привет". Это означает, что потребитель getObj () мог бы получить экземпляр, куда getValue () возвращает пустой указатель.

public class ThreadB implements Runnable {
    ThreadA a = null;

    public ThreadB(ThreadA a) {
        this.a = a;
    }

    public void run() {
        while (true) {
            try {
                System.out.println("SharedObject: " + a.getObj().getVal());
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class SharedObject {
    private String val = null;

    public SharedObject() {
    }

    public String getVal() {
        return val;
    }

    public void setVal(String val) {
        this.val = val;
    }
}
0
ответ дан 2 revs 23 November 2019 в 05:35
поделиться
while(true)
{
   if (...)
     break

   doStuff()
}

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

А именно, если тот блок не выходит, приложение и возможно даже, система запрется и умрет. Только из-за простого while(fantasy_land)...if(...) break.

0
ответ дан 2 revs, 2 users 73%Bob 23 November 2019 в 05:35
поделиться

Обновление компонента пользовательского интерфейса Swing (обычно индикатора выполнения) в рабочем потоке, а не в потоке Swing (конечно, следует использовать SwingUtilities.invokeLater (Runnable) , но если вы забудете это сделать, ошибка может проявиться долго.)

1
ответ дан 23 November 2019 в 05:35
поделиться

Неприятное попадание, которое я нашел в java, заключается в том, что несколько потоков получают доступ к HashMap без синхронизации. Если читатель читает и пишет, то есть большая вероятность того, что читатель окажется в бесконечном цикле (в зацикленном списке повреждена структура ведерного списка узлов).

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

.
0
ответ дан 23 November 2019 в 05:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: