В чем реальная польза от Неизменных Объектов? - PullRequest
0 голосов
/ 27 августа 2018

Я всегда слышу, как люди говорят, что легче управлять неизменяемыми объектами при работе с несколькими потоками, поскольку, когда один поток обращается к неизменяемому объекту, ему не нужно беспокоиться о том, что другой поток его меняет.

Ну, что произойдет, если у меня будет неизменный список всех сотрудников компании и будет нанят новый сотрудник? В этом случае неизменяемый список должен быть продублирован, а его новая копия должна включать другой объект сотрудника. Затем ссылка на список сотрудников должна быть направлена ​​на новый список.

Когда этот сценарий происходит, сам список не изменяется, но ссылка на этот список изменяется, и поэтому код «видит» разные данные.

Если это так, я не понимаю, почему неизменяемые объекты облегчают нашу жизнь при работе с многопоточностью. Что мне не хватает?

Ответы [ 2 ]

0 голосов
/ 01 апреля 2019

Вот пример: (а) у нас есть неизменный список, (б) у нас есть поток писателя, который добавляет элементы в список, и (в) 1000 потоков чтения, которые читают список без его изменения.

Он будет работать без блокировок.

Если у нас более одного потока записи, нам все равно понадобится внешний вид записи.Если нам нужно удалить записи из списка, нам понадобится блокировка чтения-записи.

Ценно ли это?Не знаю.

0 голосов
/ 27 августа 2018

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

См., Например, Java ArrayList.В нем есть поле int, содержащее текущий размер и ссылку на массив, элементы которого являются ссылками на содержащиеся объекты.Значения этих переменных должны соответствовать определенным инвариантам, например, если размер не равен нулю, ссылка на массив никогда не равна null, а длина массива всегда больше или равна размеру.При просмотре значений различных обновлений для этих переменных эти инварианты больше не сохраняются, поэтому потоки могут видеть содержимое списка, которого никогда не было в этой форме, или приводить к ошибкам с ложными исключениями, сообщая о недопустимом состоянии, которое должно быть невозможным (например, NullPointerException илиArrayIndexOutOfBoundeException).

Обратите внимание, что поточно-ориентированные или параллельные структуры данных решают только проблему, касающуюся внутренних элементов структуры данных, поэтому операции больше не завершаются ошибочными исключениями (что касается состояния коллекции, мы немы уже говорили о состоянии содержащегося элемента), но операции, повторяющиеся над этими коллекциями или смотрящие на более чем один содержащийся элемент в любой форме, все еще подвержены возможному наблюдению противоречивого состояния относительно содержащихся элементов.Это также относится к антишаблону check-then-act, где приложение сначала проверяет условие (например, используя contains), а затем воздействует на него (например, извлекает, добавляет или удаляет элемент), тогда как условие может изменитьсямежду ними.

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

Это гладко работает с языками программирования со сборкой мусора, поскольку они позволяют новой структуре данных ссылаться на старые объекты, просто заменяя измененные объекты (и их родителей), не беспокоясь о том, какие объектывсе еще используется, а который нет.

...