Ein wichtiger Punkt, der noch nicht erwähnt wurde, ist, dass es möglich ist, die Identität des Objekts, das diesen Zustand einkapselt, unveränderlich zu machen , wenn der Zustand eines Objekts veränderbar ist .
Viele Programme sind darauf ausgelegt, reale Dinge zu modellieren, die von Natur aus veränderlich sind. Angenommen, eine Variable AllTrucks
enthält um 00:51 Uhr einen Verweis auf Objekt # 451, das die Wurzel einer Datenstruktur ist, die angibt, welche Ladung in allen Lastwagen einer Flotte zu diesem Zeitpunkt (00:51 Uhr) enthalten ist, und eine Variable BobsTruck
kann verwendet werden, um einen Verweis auf Objekt # 24601 zu erhalten, der auf ein Objekt verweist, das angibt, welche Ladung sich zu diesem Zeitpunkt (00:51 Uhr) in Bobs LKW befindet. Um 00:52 Uhr werden einige Lastwagen (einschließlich Bobs) be- und entladen, und die Datenstrukturen werden aktualisiert, sodass AllTrucks
nun eine Referenz auf eine Datenstruktur enthalten ist, die angibt, dass sich die Ladung ab 00:52 Uhr in allen Lastwagen befindet.
Was soll mit passieren BobsTruck
?
Wenn die 'Fracht'-Eigenschaft jedes LKW-Objekts unveränderlich ist, repräsentiert das Objekt # 24601 für immer den Zustand, den Bobs LKW um 00:51 Uhr hatte. Wenn BobsTruck
ein direkter Verweis auf Objekt # 24601 vorhanden ist, wird der aktuelle Status von Bobs Truck nicht mehr angezeigt, es sei denn, der AllTrucks
zu aktualisierende Code wird ebenfalls aktualisiert BobsTruck
. Beachten Sie ferner, BobsTruck
dass der Code, der aktualisiert werden kann, AllTrucks
nur dann aktualisiert werden kann, wenn der Code explizit dafür programmiert wurde , es sei denn, er ist in einer Form eines veränderlichen Objekts gespeichert .
Wenn man in der Lage sein möchte, BobsTruck
den Zustand von Bobs LKW zu beobachten, während alle Objekte unveränderlich BobsTruck
bleiben , könnte man eine unveränderliche Funktion sein, die angesichts des Werts, AllTrucks
der zu einem bestimmten Zeitpunkt vorliegt oder hatte, den Zustand von Bobs LKW bei ergibt diese Zeit. Man könnte es sogar zwei unveränderliche Funktionen haben lassen, von denen eine wie oben ist und die andere einen Verweis auf einen Flottenstatus und einen neuen LKW-Status akzeptieren und einen Verweis auf einen neuen Flottenstatus zurückgeben würde passte zum alten, nur dass Bobs Truck den neuen Zustand haben würde.
Leider kann es ziemlich nervig und umständlich werden, wenn man eine solche Funktion jedes Mal verwenden muss, wenn man auf den Zustand von Bobs Truck zugreifen möchte. Ein alternativer Ansatz wäre, zu sagen, dass Objekt # 24601 immer und für immer (solange jemand einen Verweis darauf hat) den aktuellen Status von Bobs Truck darstellt. Code, der wiederholt auf den aktuellen Status von Bobs Truck zugreifen möchte, müsste nicht jedes Mal eine zeitaufwendige Funktion ausführen - er könnte einfach eine Suchfunktion ausführen, um herauszufinden, dass Objekt # 24601 Bobs Truck ist, und dann einfach Greifen Sie jederzeit auf dieses Objekt zu, um den aktuellen Status von Bobs Truck zu sehen.
Beachten Sie, dass der funktionale Ansatz in einer Umgebung mit nur einem Thread oder in einer Umgebung mit mehreren Threads nicht ohne Vorteile ist, in der Threads zumeist nur Daten beobachten und nicht ändern. Ein beliebiger Beobachter-Thread, der die in enthaltene Objektreferenz kopiertAllTrucks
Wenn Sie dann den von Ihnen dargestellten LKW-Status überprüfen, wird der Status aller LKWs ab dem Zeitpunkt angezeigt, an dem die Referenz erfasst wurde. Jedes Mal, wenn ein Beobachter-Thread neuere Daten sehen möchte, kann er die Referenz erneut abrufen. Wenn andererseits der gesamte Zustand der Flotte durch ein einziges unveränderliches Objekt dargestellt würde, würde die Möglichkeit ausgeschlossen, dass zwei Threads gleichzeitig verschiedene Lastwagen aktualisieren, da jeder Thread, wenn er seinen eigenen Geräten überlassen würde, ein neues Objekt mit dem Namen "Flottenzustand" erzeugen würde der neue Zustand seines Lastwagens und die alten Zustände von jedem anderen. Die Richtigkeit kann gewährleistet werden, wenn jeder Thread nur dann CompareExchange
zum Aktualisieren verwendet wird , AllTrucks
wenn er sich nicht geändert hat, und auf einen Fehler reagiertCompareExchange
Durch die Neuerstellung des Statusobjekts und die Wiederholung der Operation. Wenn jedoch mehr als ein Thread versucht, gleichzeitig zu schreiben, ist die Leistung im Allgemeinen schlechter als wenn alle Schreibvorgänge in einem einzigen Thread ausgeführt würden. Je mehr Threads solche gleichzeitigen Operationen ausführen, desto schlechter wird die Leistung.
Wenn einzelne LKW-Objekte veränderlich sind, aber unveränderliche Identitäten aufweisen , wird das Multithread-Szenario übersichtlicher. Es darf immer nur ein Thread gleichzeitig auf einem bestimmten LKW ausgeführt werden. Threads, die auf verschiedenen LKWs ausgeführt werden, können dies jedoch ohne Beeinträchtigung tun. Es gibt zwar Möglichkeiten, ein solches Verhalten zu emulieren, auch wenn unveränderliche Objekte verwendet werden (z. B. können die "AllTrucks" -Objekte so definiert werden, dass zum Festlegen des Zustands des zu XXX gehörenden Lastwagens für SSS lediglich ein Objekt mit der Angabe "Ab [Uhrzeit]" generiert werden muss. der Zustand des Lastwagens, der zu [XXX] gehört, ist jetzt [SSS], der Zustand von allem anderen ist [Alter Wert von AllTrucks]CompareExchange
Schleife würde nicht lange dauern. Andererseits würde die Verwendung einer solchen Datenstruktur die zum Auffinden des Lastwagens einer bestimmten Person erforderliche Zeit erheblich erhöhen. Die Verwendung von veränderlichen Objekten mit unveränderlichen Identitäten vermeidet dieses Problem.