Główną kwestią, o której jeszcze nie wspomniano, jest to, że możliwość zmiany stanu obiektu umożliwia, aby tożsamość obiektu otaczającego ten stan była niezmienna.
Wiele programów zaprojektowano do modelowania rzeczy z prawdziwego świata, które są z natury zmienne. Załóżmy, że o godzinie 12:51 jakaś zmienna AllTrucks
zawiera odniesienie do obiektu # 451, który jest rdzeniem struktury danych, która wskazuje, jaki ładunek jest zawarty we wszystkich ciężarówkach floty w tym momencie (12:51), a niektóre zmienne BobsTruck
można użyć, aby uzyskać odniesienie do obiektu # 24601 wskazuje na obiekt wskazujący, jaki ładunek znajduje się w ciężarówce Boba w tym momencie (12:51). O godzinie 12:52 niektóre ciężarówki (w tym Boba) są ładowane i rozładowywane, a struktury danych są aktualizowane, tak AllTrucks
aby zawierały teraz odniesienie do struktury danych, która wskazuje, że ładunek jest we wszystkich ciężarówkach od godziny 12:52.
Co powinno się stać BobsTruck
?
Jeśli właściwość „cargo” każdego obiektu ciężarówki jest niezmienna, wówczas obiekt # 24601 na zawsze będzie reprezentował stan, w którym ciężarówka Boba miała o 12:51. Jeśli BobsTruck
zawiera bezpośrednie odwołanie do obiektu # 24601, to jeśli kod, który aktualizuje, AllTrucks
również się aktualizuje BobsTruck
, przestanie reprezentować bieżący stan ciężarówki Boba. Zauważ też, że jeśli nie BobsTruck
jest przechowywany w jakiejś formie obiektu zmiennego, jedynym sposobem, aby aktualizowany kod AllTrucks
mógł go zaktualizować, byłby to kod zaprogramowany.
Jeśli ktoś chce mieć możliwość BobsTruck
obserwowania stanu ciężarówki Boba przy jednoczesnym zachowaniu niezmienności wszystkich obiektów, może mieć BobsTruck
niezmienną funkcję, która, biorąc pod uwagę wartość, która AllTrucks
ma lub miała w danym momencie, da stan ciężarówki Boba przy ten czas. Można nawet sprawić, by miał parę niezmiennych funkcji - z których jedna byłaby jak wyżej, a druga zaakceptowałaby odniesienie do stanu floty i nowego stanu ciężarówki, i zwróciłaby odniesienie do nowego stanu floty, który pasowało do starego, tyle że ciężarówka Boba miałaby nowy stan.
Niestety konieczność korzystania z takiej funkcji za każdym razem, gdy chcemy uzyskać dostęp do stanu ciężarówki Boba, może być dość irytująca i uciążliwa. Alternatywnym podejściem byłoby powiedzenie, że obiekt # 24601 zawsze i na zawsze (tak długo, jak ktoś ma do niego odniesienie) reprezentuje bieżący stan ciężarówki Boba. Kod, który będzie chciał wielokrotnie uzyskiwać dostęp do aktualnego stanu ciężarówki Boba, nie musiałby za każdym razem uruchamiać czasochłonnej funkcji - mógłby po prostu wykonać funkcję wyszukiwania, aby dowiedzieć się, że obiekt # 24601 jest ciężarówką Boba, a następnie po prostu dostęp do tego obiektu za każdym razem, gdy chce zobaczyć obecny stan ciężarówki Boba.
Zauważ, że podejście funkcjonalne nie jest pozbawione zalet w środowisku jednowątkowym lub w środowisku wielowątkowym, w którym wątki przeważnie tylko obserwują dane, a nie je zmieniają. Każdy wątek obserwatora, który kopiuje odwołanie do obiektu zawarte wAllTrucks
a następnie sprawdza reprezentowane stany ciężarówek, dzięki czemu zobaczy stan wszystkich ciężarówek w momencie, w którym chwycił odniesienie. Za każdym razem, gdy wątek obserwatora chce zobaczyć nowsze dane, może po prostu ponownie pobrać referencję. Z drugiej strony posiadanie całego stanu floty reprezentowanego przez jeden niezmienny obiekt wykluczałoby możliwość jednoczesnego aktualizowania różnych ciężarówek przez dwa wątki, ponieważ każdy wątek pozostawiony własnym urządzeniom wytworzyłby nowy obiekt „stanu floty”, który obejmowałby nowy stan jego ciężarówki i stare stany każdego innego. Poprawność można zapewnić, jeśli każdy wątek używa CompareExchange
do aktualizacji AllTrucks
tylko wtedy, gdy się nie zmienił i reaguje na awarięCompareExchange
przez ponowne wygenerowanie obiektu stanu i ponowienie operacji, ale jeśli więcej niż jeden wątek podejmie operację jednoczesnego zapisu, wydajność będzie na ogół gorsza niż w przypadku, gdy wszystkie zapisy zostały wykonane w jednym wątku; im więcej wątków podejmie takie jednoczesne operacje, tym gorsza będzie wydajność.
Jeśli poszczególne obiekty ciężarówki są zmienne, ale mają niezmienne tożsamości , scenariusz wielowątkowy staje się czystszy. Tylko jeden wątek może być dopuszczony do działania w danym momencie na danej ciężarówce, ale wątki działające na różnych ciężarówkach mogą to robić bez ingerencji. Chociaż istnieją sposoby naśladowania takiego zachowania, nawet przy użyciu niezmiennych obiektów (np. Można zdefiniować obiekty „AllTrucks”, aby ustawienie stanu ciężarówki należącej do XXX do SSS wymagało po prostu wygenerowania obiektu o treści „Na [Czas], stan ciężarówki należącej do [XXX] to teraz [SSS]; stan wszystkiego innego to [Stara wartość AllTrucks] ”. Wygenerowanie takiego obiektu byłoby wystarczająco szybkie, aby nawet w przypadku sporu,CompareExchange
pętla nie potrwa długo. Z drugiej strony użycie takiej struktury danych znacznie zwiększyłoby czas potrzebny na znalezienie ciężarówki konkretnej osoby. Używanie obiektów zmiennych z niezmiennymi tożsamościami pozwala uniknąć tego problemu.