JS моделирует параллелизм в цикле событий. В результате нет гоночных условий.
Это не совсем исчерпывающе, вы также можете получить параллелизм в javascript, запустив вашу программу на нескольких дочерних процессах , и в этом случае несколько потоков могут изменять одну ссылку на памятьдействительно может привести к гоночным условиям или тупикам. И да, неизменность - это один из шаблонов проектирования, принятых для обеспечения поточной безопасности : [в основном] путем принудительного предоставления общих данных только для чтения .
ЭтоХорошая статья , объясняющая, почему и как вы можете столкнуться с условиями гонки в многопоточной среде, такой как Java.
Вы правы, нет ничего плохого в мутировании ссылок на память воднопоточные языки, на самом деле, так было сделано в течение очень долгого времени в javascript. Неизменность набрала обороты только недавно. Гилель Уэйн также объясняет, как удаление параллелизма полностью помогает снять боль, вызванную изменчивостью.
Но я бы лучше решил этот вопрос с другой точки зрения: Изменчивость представляет собой архитектурнуюпроблема и она является трансверсальной для каждого языка программирования или среды, независимо от того, является ли она многопоточной или однопоточной, на самом деле не имеет значения.
Легко понять, подумав с архитектурой, как изменчивость приводит к непредсказуемому программному обеспечению. Гарантирует ли что-либо, что при определенных условиях объект будет находиться в определенном состоянии? На самом деле, нет. Сколько объектов может вызвать изменение состояния данного объекта? Могут ли эти изменения быть под контролем? Не совсем, думать о переменной в основной области видимости ... буквально все может повлиять на ее состояние, и предположения типа " каждая операция, которую следует учитывать [...] " небезопасны и очень подвержены ошибкам.
Итак, хотя изменчивость не обязательно является неправильной, Неизменяемость - это еще один инструмент в наборе инструментов вашего разработчика , и его освоение делает вас лучшим разработчиком.
Неизменяемая структура данных (неизменяемый объект)поддерживает только одну операцию: чтение, и это приводит к тому, что ваша программа ведет себя как машина Мура: , учитывая конкретный момент времени, ваша программа всегда будет в одном из возможных состояний .
ВашПрограмма - это конвейер операций, который всегда можно рассчитать и измерить:
R.pipe(
R.toUpper, // You know the state of your program here
R.concat(R.__, '!!'), // or here
)('Hello World'); // or here
Вы также можете поменять местами один из этапов с его возвращаемым значением и при этом ваша программа будет вести себя как положено:
R.pipe(
R.always('HELLO WORLD'),
R.concat(R.__, '!!'),
)('Hello World');
Неизменность также позволяет путешествовать во времени и делает тестирование очень простым, но что действительно важно, так это то, что делаеточень просто рассуждать о состояниях и их переходах только потому, что вы рассматриваете каждое значение как примитив: user.set('name', 'Giuseppe')
становится не отличным от 'Giuseppe'.toUpperCase()
.
Ваша программа в конечном итоге представляет собой четко определенную сериюмоментальные снимки:
-> 'Hello World' -> 'HELLO WORLD' -> 'HELLO WORLD!!'
t(0) ----------- t(1) ----------- t(2) ------------- t(n)
Примечания. В то время как у вас есть больше промежуточных значений, постоянство также дает вам выигрыш в производительности, поскольку глубокое равенство бессмысленно.
const user = { name: 'Giuseppe' };
const equals = (given, expected) => given === expected;
const newUser = { ...user, name: 'Marco' };
console.log('are users equals:', equals(user, newUser));
Вам потребуется функция deepEqual для получения того же результата с изменчивостью ... (подробнее на веб-сайте redux )