Поскольку многоядерные процессоры становятся все более распространенными, возможность писать программы, использующие все доступные процессоры, становится все более важной.
Давайте разберемся, почему существующие широко используемые средства написания программ для многоядерных процессоров не являются достаточно хорошим решением, что такое транзакционная память и как она решает эту проблему.
Обычно программы (если они не написаны на чисто функциональном языке) имеют изменяемые области памяти, в которых хранятся данные программы.
Если в программе есть несколько потоков управления, которые работают с этими данными, то важно, чтобы доступ к ним был структурирован таким образом, чтобы не возникало проблем параллелизма, таких как чтение области памяти, которая записывается параллельно из другого потока, или запись из двух потоков одновременно.
Наиболее распространенным средством синхронизации доступа к данным в программах, написанных на императивных языках, является блокировка.
Прежде чем получить доступ к данным, их необходимо заблокировать; если блокировка уже занята, поток ожидает момента снятия блокировки.
Таким образом, мы можем быть уверены, что к одним и тем же данным никогда не будет обращаться более одного потока.
К сожалению, здесь есть проблема.
Я бы хотел, чтобы много потоков могли работать одновременно.
Поэтому логично было бы структурировать программу так, чтобы каждая более-менее независимая часть данных программы имела свою блокировку.
Но когда у нас много блокировок, возможны взаимоблокировки: в случае, когда блокировки берутся в другом порядке.
Чтобы сразиться с ними, нужно в том же порядке брать замки.
Для этого для каждого метода нужно понимать, какие блокировки может брать тот, кто его вызывает, и какие блокировки можно брать во время этого вызова, и следить за тем, чтобы порядок блокировок всегда был одинаковым.
Заставить это работать очень сложно, и даже если программа работает, неосторожное добавление вызова не в том месте может привести к тупику.
Что может быть альтернативой блокировке? Одним из решений проблемы доступа к общим данным является транзакционная память.
Транзакционная память позволяет работать с данными, используя транзакции, аналогичные транзакциям базы данных.
Транзакции выполняются так, как будто текущая транзакция является единственной операцией с текущими данными.
Когда транзакция завершена, она проверяет, были ли какие-либо конфликты с другими транзакциями.
Если их не было (наиболее вероятный вариант), изменение принимается; в противном случае транзакция повторяется снова.
В программах, имеющих большое количество потоков, работающих с разными областями памяти, такая конструкция будет работать очень хорошо: конфликты будут редки, а степень параллелизма будет высокой.
К сожалению, есть и недостатки: в транзакционных блоках желательно не вызывать код, имеющий побочные эффекты: ввод/вывод, рисование на экране и т.п.
В настоящее время существует довольно большое количество библиотек (например, Мультиверсия для Java), которые позволяют использовать этот подход в существующих языках программирования, а также в некоторых языках (Fortress, Clojure), поддерживающих напрямую транзакционную память.
Теги: #транзакционная память #многоядерность #параллелизм #разработка веб-сайтов
-
Colordotnet: Универсальный Магазин Hd-Обоев
19 Oct, 24 -
Руководство: Ваш Собственный L2Tp Vpn
19 Oct, 24 -
Ваш Домашний Сервер
19 Oct, 24 -
Вим 7.3 Вышел
19 Oct, 24 -
Международная Зачистка От Google
19 Oct, 24 -
На Своем Рабочем Месте Вы:
19 Oct, 24