Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
курсовик.doc
Скачиваний:
18
Добавлен:
08.02.2015
Размер:
326.14 Кб
Скачать

4.2. Голодание (starvation).

Проблема полной недоступности ресурсов определённому потоку в связи с потреблением их другими потоками. Может проявляется при некорректном планирования выполнения (например различие в приоритетах на определённых системах), либо более частый случай - ошибки при проектировании и реализации. Если у одного потока будет выставлен очень высокий приоритет, а у другого низкий, то первый может потреблять существенную все вычислительные ресурсы, в то время как второй не получит их вовсе. К счастью, такое поведение практически невозможно на большинстве платформ поддерживаемых Java. В то время как ошибки при проектировании и реализации приводящие к проблеме голодания вполне реальны. Например ошибка некорректной обработки условия выхода из цикла выполняющегося при захваченной блокировке, которую ожидает другой поток.

Пример 12.

public class Starvation {

     public static void main(String[] args) {

        final ReentrantLock lock1 = new ReentrantLock();

        Thread t = new Thread(new Runnable() {

            @Override

            public void run() {

                delay();//реализация аналогична DeadLock

                lock1.lock();

                try {

                    //критическая секция

                    System.out.println("completed");

                }

                finally {

                    lock1.unlock();

                }

            }

        }, "slave");

        t.start();

         lock1.lock();

        try {

            while (!Thread.currentThread().isInterrupted()) {

                //условие выхода которое не наступает

            }

        }

        finally {

            lock1.unlock();

        }

        System.out.println("finished");

    }

}

Детектирование проблемы голодания не столь прямолинейно как в случае с взаимной блокировкой. Если ситуация подобна примеру, то можно легко вычислить не ожидающий поток с бесконечным циклом любой утилитой отображающей состояние процессов и потоков в операционной системе. Далее получить дамп потоков и определить место возникновения проблемы. Но если в такой ситуации внутри цикла поток будет блокироваться в ожидании события или просто отдавать рекомендацию планировщику (Thread.yield, Thread.sleep) уступить текущий квант, то определить её будет сложнее. При подобных условиях могут пригодиться как ручное наблюдение за стеками выполнения и состояниями потоков во времени, так и автоматическое профилирование приложения (может понадобиться длительное время сбора статистики).

4.3. Активная блокировка (livelock) .

Это зацикливание алгоритма в результате взаимодействия состоянием, которое в свою очередь может независимо изменяться извне. Условие существование изменяемого извне состояния - параллелизм (необязательно многопоточность, например, взаимодействие процессов с файловой системой). При активной блокировки поток не блокируется, а продолжает попытки выполнить полезное действие, но в результате некорректной обработки ошибки при его выполнение повторяет его снова. Например завершение транзакции в СУБД, которая не может быть выполнена по причине нарушения в работе сервера, но некорректный код трактует ошибку как временную и пытается повторить транзакцию. Ещё один классический пример из области сетевых технологий. Если два или более передающих устройства одновременно пытаются передать данные, то обнаруживая коллизию и повторяя попытки передачи через равные интервалы времени ни одно устройство не сможет ничего передать, так как каждый раз разделяемая среда будет передавать сигналы нескольких источников. 

Помимо таких явных проблем блокирующих выполнение, как упомянутые выше в этой секции, существуют и менее критичные проблемы производительности и латентности (времени реакции). Наверное, наиболее распространённым их видом, связанным с производительностью, будет являться проблема со слабо гранулированными блокировками (coarse-grained lock) или их экстремальным вариантом - глобальными блокировками (global lock). Суть этой проблемы сводится к тому, что в результате больших размеров критической секции выполнение на этом участке фактически сериализуется (смотри 2.4 Блокировки). К проблемам латентности можно отнести ситуацию близкую к голоданию, когда какой-то поток практически не получает время центрального процессора или прочий ресурс, в результате чего растягивается время выполнения операции.