Как функциональные языки обрабатывают данные общего состояния? - PullRequest
0 голосов
/ 23 октября 2018

Я изучал функциональное программирование и вижу, что оно, безусловно, может облегчить параллелизм, но я не понимаю, как оно облегчает обработку общих ресурсов.Я видел, как люди говорили о том, что переменная неизменность является ключевым фактором, но как это помогает двум потокам обращаться к одному и тому же ресурсу?Скажем, два потока добавляют запрос в очередь.Они оба получают копию очереди, делают новую копию с добавленным запросом (поскольку очередь неизменна), а затем возвращают новую очередь.Первый запрос на возврат будет переопределен вторым, так как копии очереди, полученные каждым потоком, не имели запроса другого потока.Таким образом, я предполагаю, что есть механизм блокировки а-ля мьютекс, доступный на функциональных языках?Чем же это отличается от императивного подхода к проблеме?Или практические приложения функционального программирования все еще требуют некоторых обязательных операций для управления общими ресурсами?

1 Ответ

0 голосов
/ 23 октября 2018

Как только ваши глобальные данные могут быть обновлены.вы нарушаете чистую функциональную парадигму.В этом смысле вам нужна какая-то императивная структура.Тем не менее, это достаточно важно, чтобы большинство функциональных языков предлагали способ сделать это, и вам нужно, чтобы он в любом случае мог общаться с остальным миром.(Самым сложным формальным является монада IO в Haskell.) Помимо простых привязок для некоторой другой библиотеки синхронизации, они, возможно, попытались бы реализовать структуру данных без блокировки и без ожидания, если это возможно.

Некоторые подходы включают:

  • К данным, которые записываются только один раз и никогда не изменяются, можно безопасно получить доступ без блокировок или ожидания на большинстве процессоров.(Обычно существует инструкция ограничения памяти, чтобы гарантировать, что память обновляется в правильном порядке как для производителя, так и для потребителя.)
  • Некоторые структуры данных, такие как список различий, имеют свойство, которое можно использоватьна обновления без аннулирования каких-либо существующих данных.Допустим, у вас есть список ассоциаций [(1,'a'), (2,'b'), (3,'c')], и вы хотите обновить его, изменив третью запись на 'g'.Если вы выражаете это как (3,'g'):originalList, то вы можете обновить текущий список новой версией и оставить originalList действительным и неизменным.Любой поток, который видел его, все еще может безопасно использовать его.
  • Даже если вам придется работать с сборщиком мусора, каждый поток может сделать свою собственную локальную для потока копию общего состояния, пока оригинал не получитудаляется во время копирования.Базовая низкоуровневая реализация будет представлять собой модель производителя / потребителя, которая атомарно обновляет указатель на данные состояния и вставляет инструкции ограничения памяти перед операциями обновления и копирования.
  • Если в программе есть способ сравнения-и поменяйте местами атомарно, и сборщик мусора знает, что каждый поток может использовать шаблон получения-копирования-обновления.Сборщик мусора с поддержкой потоков будет хранить старые данные до тех пор, пока их использует любой поток, и перерабатывать их, когда последний поток завершит работу с ними.Это не должно требовать блокировки в программном обеспечении (например, в современных ISA увеличение или уменьшение счетчика размера слова является атомарной операцией, а атомарное сравнение-и-замена не требует ожидания).
  • Функциональный языкМожно добавить расширение для вызова библиотеки IPC, написанной на другом языке, и обновить данные на месте.В Haskell это было бы определено с помощью монады IO для обеспечения последовательной согласованности памяти, но почти каждый функциональный язык имеет некоторый способ обмена данными с системными библиотеками.

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

...