Rubin - unveränderliche Objekte
-
03-07-2019 - |
Frage
Ich habe eine sehr multithreaded app in Ruby geschrieben habe, dass einige Instanzvariablen teilt. Schreibt auf diese Variablen sind selten (1%), während liest sind sehr häufig (99%). Was ist die beste Art und Weise (entweder Ihrer Meinung oder in der idiomatischen Ruby-Mode) ist, um sicherzustellen, dass diese Fäden der meisten up-to-date beteiligt Werte immer sehen? Hier einige Ideen so weit, dass ich hatte ( obwohl ich Ihre Eingabe möchte, bevor ich diese Überholung):
- Haben Sie eine Sperre, die am meisten verwendet werden, bevor das Lesen oder eine dieser Variablen zu schreiben (von Java Concurrency in Practice ). Die Kehrseite der Medaille ist, dass es eine Menge
synchronize
Blöcke in meinem Code steckt, und ich sehe nicht, eine einfache Möglichkeit, es zu vermeiden. - Verwenden Sie Rubys
freeze
Methode (siehe hier ), obwohl es ebenso umständlich und doesn sieht‘ t geben Sie mir eine der Synchronisations Vorteile, die die erste Option gibt.
Diese Optionen scheinen beide ziemlich ähnlich, aber hoffentlich jemand da draußen eine bessere Idee haben (oder kann auch für eine dieser Ideen argumentieren). Ich würde auch in Ordnung sein mit der Herstellung der Objekte unveränderlich, so dass sie in der Mitte einer Operation nicht beschädigt oder verändert, aber ich weiß nicht, Rubin gut genug, um den Anruf auf meinem eigenen und this Frage scheint zu argumentieren, dass Objekte sind sehr wandelbar.
Lösung
das Schloss zu verwenden ist die passende Art, dies zu tun. Sie können diese Präsentation von Jim Weirich zu diesem Thema finden Sie unter: Alle Rubyist über Threading wissen sollte.
Auch ein Objekt Einfrieren werden Sie hier nicht helfen, da Sie diese Variablen ändern möchten. sie an ihrem Platz Einfrieren bedeutet, dass keine weiteren Änderungen an diesen anwendbar sind (und damit Ihr 1% von Schreibvorgängen wird nicht funktionieren).
Andere Tipps
Ich habe es selbst nicht verwendet, aber Sie können Dataflow . Es macht alle Variablen write-once.
Die Leser-Schreiber-Sperre ist ein häufiges Problem mit einer gut definierten Lösung:
und es gibt viele Implementierungen davon:
Sie wollen nicht eine Sperre auf setzen für jeden Lese- / Schreib
Sie haben einen Mutex verwenden, um Zugriff auf den gemeinsam genutzten Zustand zu synchronisieren. Es gibt wirklich keine Möglichkeit, dies zu tun zu vermeiden.
Auf modernen Multi-Core-Maschinen können Sie keine Annahmen darüber, wie wird Speicher zugegriffen werden oder wie Speicher mit Caching interagieren zugreift.