2014-02-06 6 views
5

Ich habe gelesen und heard eine Menge guter Dinge über immutability, also habe ich beschlossen, es in einem meiner Hobby-Projekte auszuprobieren. Ich habe alle meine Felder als schreibgeschützt deklariert und alle Methoden gemacht, die normalerweise ein Objekt mutieren würden, um eine neue, modifizierte Version zurückzugeben.Wie implementiere ich Caching auf unveränderliche Weise?

Es funktionierte großartig, bis ich in eine Situation kam, in der eine Methode durch externes Protokoll eine bestimmte Information über ein Objekt zurückgeben sollte, ohne sie zu modifizieren, aber gleichzeitig durch Modifikation der internen Struktur optimiert werden konnte. Dies geschieht insbesondere mit tree path compression in einem union find algorithm.

Wenn der Benutzer int find(int n) aufruft, erscheint das Objekt für den Außenstehenden unverändert. Es stellt die gleiche Entität konzeptionell dar, aber die internen Felder sind mutiert, um die Laufzeit zu optimieren.

Wie kann ich das auf unveränderliche Weise implementieren?

+2

Ich würde sagen, dass, wenn Sie die Mutation in einer thread-sicheren Weise tun, und es von einem Außenseiter nicht nachweisbar ist, dann kann es als unveränderlich angesehen werden. – Joe

+0

@Joe aber so muss ich die Fadensicherheit selbst beibehalten. Die Schönheit der Unveränderlichkeit, so wie ich sie verstehe, ist die Tatsache, dass ich es der Sprache überlassen kann, indem ich nur das Schlüsselwort readonly festlege. –

+0

aber Sie haben gesagt, dass Sie es mutieren wollen. Wenn Sie dies nicht thread-sicher tun, verlieren Sie einen der Vorteile eines unveränderlichen Typs (Thread-Sicherheit). – Joe

Antwort

2

Kurze Antwort: Sie müssen die Fadensicherheit selbst sicherstellen.

Das Schlüsselwort readonly in einem Feld gibt Ihnen die Sicherheit, dass das Feld nicht geändert werden kann, nachdem das Objekt mit diesem Feld erstellt wurde. Der einzige Schreibvorgang, den Sie für dieses Feld haben können, ist also im Konstruktor (oder in der Feldinitialisierung) enthalten, und ein Methodenaufruf kann nicht ausgeführt werden, bevor das Objekt erstellt wird, daher die Thread-Sicherheit von readonly.

Wenn Sie Caching implementieren möchten, brechen Sie die Annahme, dass nur ein Schreibvorgang auftritt (da "caching writes" während des Lesens auftreten kann und wird), und daher kann es in schlechten Fällen zu Threading-Problemen kommen Lesen von Zeilen aus einer Datei, zwei Threads können die find-Methode mit dem gleichen Parameter aufrufen, lesen aber zwei verschiedene Zeilen und erhalten dadurch unterschiedliche Ergebnisse. Was Sie implementieren möchten, ist observational immutability. Diese related question about memoization kann Ihnen mit einer eleganten Antwort helfen.

Verwandte Themen