будет устанавливаться обрамляющим catch-блоком кода потока, флаг
завершения — каждым потоком перед успешным завершением. Для
всех потоков следует создать один общий флаг исключения, устана-
вливаемый вместе с флагом потока.
Шаг 3.
Для каждой переменной, которая останется активной в слу-
чае генерации исключения, создать список, каждый элемент которого
является парой временн´ая метка–значение. Каждый поток вместо за-
писи непосредственно в переменную должен выполнить запись в этот
список.
Шаг 4.
Перед каждым оператором, имеющим временн´ую метку,
при генерации исключения устанавливается его временной штамп. Та-
ким образом, после завершения всех потоков можно узнать, на какой
именно временн´ой метке остановился каждый поток.
Шаг 5.
Если при генерации исключения поток занимал объект
синхронизации, то этот объект должен быть освобожден либо в finally-
блоке обрамляющего try-блока, либо другим способом, например с
помощью освобождающего деструктора в модели RAII, как в языке
C++.
Шаг 6.
При выходе из распараллеленной секции в однопоточный
код, если установлен флаг исключения, среди потоков, сгенерировав-
ших исключение, необходимо найти поток с минимальной временн ´ой
меткой. Значением переменной будет значение из списка, соответству-
ющее предыдущей временн´ой метке.
Предложенный алгоритм допускает выполнение операций, кото-
рые могут быть не реализованы в случае генерации исключения. Под-
ход, при котором осуществляются операции, результат которых мо-
жет быть не использован при дальнейшем выполнении программы,
называется
спекулятивным выполнением
. Такой подход применяется в
микроэлектронике при разработке процессоров для повышения произ-
водительности работы конвейеров. В работе [11] описаны различные
оптимизации генерируемых кодов программ, связанные со спекулятив-
ным выполнением и осуществляемые на этапе компиляции исходных
кодов.
Для уменьшения размера результирующего кода, а также ускорения
результирующей программы, можно вместо списка записей использо-
вать одномерный массив, размер которого равен числу потоков. Этот
прием можно применять в тех случаях, когда диапазоны временн ´ых
меток строго разделены. Кроме того, можно добавлять в код создавае-
мых потоков периодические проверки на произошедшее исключение,
что позволит быстро завершить работу оставшихся потоков в случае,
когда один из них сгенерировал исключение.
Примеры.
Рассмотрим несколько примеров распараллеливания ко-
да цикла на языке Java с помощью предлагаемого метода.
76 ISSN 0236-3933. Вестник МГТУ им. Н.Э. Баумана. Сер. “Приборостроение”. 2014. № 6