Основний момент, який ще не згадується, - це те, що стан об'єкта, який може бути змінним, дає змогу ідентичність об'єкта, яка інкапсулює цей стан, незмінна.
Багато програм створені для моделювання реальних речей, які за своєю суттю змінюються. Припустимо, що о 12:51, деяка змінна AllTrucks
містить посилання на об'єкт № 451, що є коренем структури даних, яка вказує, який вантаж міститься у всі вантажні машини флоту в цей момент (12:51 ранку), а який - змінний BobsTruck
може бути використаний для отримання посилання на об'єкт №24601 вказує на об'єкт, який вказує, який вантаж міститься в вантажівці Боба в цей момент (12:51 ранку). О 12:52 ранку деякі вантажівки (включаючи Боба) завантажуються та вивантажуються, а структури даних оновлюються так, що AllTrucks
тепер буде посилатися на структуру даних, яка вказує, що вантаж знаходиться у всіх вантажівок станом на 12:52 ранку.
Що має статися BobsTruck
?
Якщо властивість «вантажу» кожного об'єкта вантажівки буде непорушною, то об’єкт №24601 назавжди буде представляти стан, який мав вантажівка Боба о 12:51 ранку. Якщо BobsTruck
має пряме посилання на об’єкт №24601, то, якщо код, який оновлення AllTrucks
також не оновлюється BobsTruck
, він перестане представляти поточний стан вантажівки Боба. Далі зауважте, що якщо BobsTruck
не зберігається в якійсь формі об'єкта, що змінюється, єдиний спосіб, коли код, який оновлення AllTrucks
міг би оновити, був би, якщо код був явно запрограмований для цього.
Якщо хтось хоче мати можливість BobsTruck
спостерігати за станом вантажівки Боба, зберігаючи всі непорушні об'єкти, може BobsTruck
бути незмінна функція, яка, зважаючи на значення, яке AllTrucks
має або було в будь-який конкретний час, призведе до стану вантажівки Боба на того часу. Можна навіть мати, щоб він виконував пару незмінних функцій - одна з яких була б, як вище, а друга з яких приймала б посилання на стан флоту та новий стан вантажівки, а також повертала посилання на новий стан флоту, який відповідає старому, за винятком того, що вантажівка Боба мала б новий стан.
На жаль, використання такої функції кожного разу, коли хочеться отримати доступ до штату вантажівка Боба, може стати досить дратівливою і громіздкою. Альтернативним підходом було б сказати, що об'єкт №24601 завжди і назавжди (доки хтось має на нього посилання) буде представляти поточний стан вантажівки Боба. Код, який бажає неодноразово отримувати доступ до поточного стану вантажівки Боба, не повинен був би виконувати деяку трудомістку функцію кожного разу - він може просто виконувати функцію пошуку один раз, щоб дізнатися, що об’єкт №24601 - вантажівка Боба, а потім просто отримати доступ до цього об'єкта будь-коли, коли він хоче побачити сучасний стан вантажівки Боба.
Зауважте, що функціональний підхід не позбавлений переваг в однопотоковому середовищі або в багатопотоковому середовищі, де потоки здебільшого просто спостерігатимуть дані, а не змінюватимуть їх. Будь-яка нитка спостерігача, яка копіює посилання на об'єкт, що міститься вAllTrucks
а потім вивчає представлені таким чином стани вантажівки, побачить стан усіх вантажних автомобілів станом на той момент, коли він схопив посилання. Кожен раз, коли нитка спостерігача хоче побачити новіші дані, вона може просто знову захопити посилання. З іншого боку, наявність усього штату флоту, представленого одним незмінним об'єктом, виключає можливість одночасного оновлення двох потоків різних вантажних автомобілів, оскільки кожен потік, якщо залишити його на власні пристрої, створював би новий об'єкт "стан флоту", який включає новий стан своєї вантажівки та старі штати кожного іншого. Правильність може бути гарантована, якщо кожен потік використовує CompareExchange
для оновлення AllTrucks
лише те, що він не змінився і відповідає на помилкуCompareExchange
шляхом регенерації об'єкта стану та повторної операції, але якщо одночасна операція запису намагається більше ніж один потік, продуктивність, як правило, буде гіршою, ніж якщо б усі записи були виконані на одному потоці; чим більше ниток намагаються проводити такі одночасні операції, тим гірше буде отримати продуктивність.
Якщо окремі об'єкти вантажних автомобілів є змінними, але мають незмінні ідентичності , багатопотоковий сценарій стає більш чистим. На будь-якому вантажівці одночасно може працювати лише одна нитка, але нитки, що працюють на різних вантажних автомобілях, можуть робити це без втручання. Хоча існують способи, які можна наслідувати такій поведінці навіть при використанні незмінних об'єктів (наприклад, можна визначити об'єкти "AllTrucks", щоб встановлення стану вантажівки, що належить до XXX, до SSS, просто вимагало б створити об'єкт, який сказав "Станом на [Час]", стан вантажівки, що належить до [XXX], зараз є [SSS]; стан всього іншого - [стара цінність AllTrucks] ". Створення такого об'єкта було б досить швидким, що навіть за наявності суперечкиCompareExchange
петля не займе багато часу. З іншого боку, використання такої структури даних суттєво збільшить час, необхідний для пошуку вантажівки конкретної людини. Використання змінних об'єктів з незмінною ідентичністю дозволяє уникнути цієї проблеми.