Подтвердить что ты не робот

Что такое Clojure volatile?

В недавнем выпуске Clojure 1.7 добавлено дополнение: volatile!

volatile уже используется на многих языках, включая java, но какова семантика в Clojure?

Что он делает? Когда это полезно?

4b9b3361

Ответ 1

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

От объявление:

существует новый набор функций (volatile!, vswap!, vreset!, volatile?) для создания и использования изменчивых "ящиков" для хранения состояния в преобразователях состояния. Летучие вещества быстрее, чем атомы, но отказываются от атомных гарантий, поэтому их следует использовать только при изоляции резьбы.

Например, вы можете установить/получить и обновить их так же, как если бы вы сделали с переменной в C. Единственным добавлением (и, следовательно, именем) является ключевое слово volatile для фактического java-объекта.

Это предотвращает оптимизацию JVM и гарантирует, что он считывает местоположение памяти каждый раз, когда к ней обращаются. Из билет JIRA:

Clojure нужен более быстрый вариант Atom для управления внутренними преобразователями. То есть, Атомы выполняют эту работу, но они обеспечивают слишком много возможностей для целей преобразователей. В частности, семантика сравнения и свопа Атомов добавляет слишком много накладных расходов. Поэтому было установлено, что простой волатильный тип ref будет работать для обеспечения основного распространения его значения на другие потоки и чтения последней записи из любого другого потока. Хотя обновления зависят от условий гонки, доступ контролируется гарантиями JVM.

Обзор решений. Создайте конкретный тип в Java, сродни clojure.lang.Box, но волатильный внутри поддерживает IDeref, но не часы и т.д.

Это означает, что a volatile! можно получить доступ к нескольким потокам (что необходимо для преобразователей), но оно не позволяет изменяться этими потоками одновременно, поскольку оно дает вам нет обновлений атома.

Семантика того, что делает volatile, очень хорошо объясняется в java-ответе:

существует два аспекта безопасности потоков: (1) контроль выполнения и (2) видимость памяти. Первое связано с контролем при выполнении кода (включая порядок выполнения инструкций) и может ли он выполняться одновременно, а второй - когда эффекты в памяти о том, что было сделано, видны другим потокам. Поскольку каждый процессор имеет несколько уровней кэша между ним и основной памятью, потоки, выполняемые на разных процессорах или ядрах, могут видеть "память" по-разному в любой момент времени, поскольку потокам разрешено получать и работать с частными копиями основной памяти.

Теперь посмотрим, почему бы не использовать var-set или transients:

Volatile vs var-set

Богатый Хикки не хотел давать действительно изменяемые переменные:

Без изменчивых локальных жителей люди вынуждены использовать recur, функциональный цикл. Хотя сначала это может показаться странным, это так же кратко, как петли с мутацией, и результирующие узоры могут быть повторно используется в другом месте в Clojure, то есть повторять, уменьшать, изменять, коммутировать и т.д. все (логически) очень похожи. [...] В любом случае, Vars доступны для использования, когда это необходимо.

И, таким образом, создавая with-local-vars, var-set и т.д. Проблема заключается в том, что они true vars, а строка doc var-set сообщает вам:

var должен быть привязан к потоку.

Это, конечно, не опция для core.async, которая потенциально выполняется на разных потоках. Они также намного медленнее, потому что они выполняют все эти проверки.

Почему бы не использовать переходные процессы

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

Резюме:

Volatile - это не что иное, как обертка вокруг java volatile и, следовательно, такая же семантика. Никогда не делитесь ими. Используйте их только очень осторожно.

Ответ 2

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

существует новый набор функций (volatile!, vswap!, vreset!, volatile?) для создания и использования изменчивых "ящиков" для хранения состояния в преобразователях состояния. Летучие вещества быстрее, чем атомы, но отказываются от атомных гарантий, поэтому их следует использовать только с изолированием резьбы