Frage

Wenn ich erstelle Klassen, die nur in einem einzigen Thread zur Zeit verwendet werden, soll ich sie mache Thread-sicher, auch wenn ich im Moment, dass nicht brauchen? Es könnte sein, passieren, dass ich später diese Klasse in mehrere Threads verwenden, und zu dieser Zeit konnte ich Rennbedingungen erhalten und eine harte Zeit haben, sie zu finden, wenn ich nicht die Klasse Thread-sicher in erster Linie gemacht haben. Oder sollte ich die Klasse machen nicht Thread-sicher, für eine bessere Leistung? Aber vorzeitige Optimierung ist böse.

anders gefragt: Soll ich meine Klassen Thread-sicher, wenn nötig machen (wenn in mehreren Threads verwendet, sonst nicht) oder sollte ich dieses Problem optimieren dann erforderlich (wenn ich, dass die Synchronisation sehen einen wichtigen Teil der Verarbeitungszeit frisst) ?

Wenn ich eine der beiden Möglichkeiten wählen, gibt es Methoden, um die Nachteile zu reduzieren? Oder besteht eine dritte Möglichkeit, dass ich verwenden soll?

Bearbeiten : Ich gebe den Grund dieser Frage meiner Meinung nach kam. In unserem Unternehmen haben wir eine sehr einfache Benutzerverwaltung geschrieben, dass die Daten in Immobilien-Dateien schreibt. Ich benutzen es in einem Web-App und nach einiger Arbeit daran Ich habe seltsame Fehler, dass das Benutzer-Management über Eigenschaften von Benutzern vergessen hat (einschließlich Namen und Passwort) und Rollen. Das war sehr ärgerlich, aber nicht konsequent reproduzierbar, so dass ich glaube, es war Race-Bedingung. Da ich alle Methoden synchronisiert Lesen und von / auf Festplatte zu schreiben, verschwand das Problem. Also dachte ich, dass ich wahrscheinlich alle den Ärger hätte vermieden werden können, wenn wir die Klasse mit der Synchronisation in erster Linie geschrieben hatte?

EDIT 2 : Wie ich über die Spitzen von Pragmatische Programmierer sehen, ich sah Spitze # 41: Immer Entwurf für Concurrency. Das heißt nicht, dass alle Code sollten Thread-sicher sein, aber es sagt der Entwurf, den die Gleichzeitigkeit im Auge haben sollte.

War es hilfreich?

Lösung

aus den Daten starten. Entscheiden Sie, welche Daten explizit freigegeben wird und schützen. Wenn möglich, kapselt die Verriegelung mit den Daten. Verwenden Sie bereits bestehenden Thread-sichere gleichzeitige Sammlungen.

Wenn möglich, verwenden Sie unveränderliche Objekte. Machen Sie Attribute final, setzen ihre Werte in der Konstrukteurs. Wenn Sie auf „ändern“ müssen die Daten betrachten eine neue Instanz zurück. Unveränderliche Objekte müssen Verriegelung nicht.

Für Objekte, die nicht mit anderen geteilt werden oder faden beschränkt, verbringen nicht Zeit, sie Thread-sicher zu machen.

Dokument die Erwartungen in den Code. Die JCIP Anmerkungen sind die beste vordefinierte Auswahl zur Verfügung.

Andere Tipps

Früher habe ich alles zu versuchen, Thread-sicher zu machen - dann erkannte ich, dass die eigentliche Bedeutung von „thread-safe“ auf der Nutzung abhängt. Sie können oft einfach nicht, dass die Nutzung vorhersagen, und der Anrufer wird wird Maßnahmen zu ergreifen, trotzdem ist es in einem Thread-sichere Art und Weise zu nutzen.

In diesen Tagen schreibe ich fast alles, was Single-Threading unter der Annahme, und das Wissen in den wenigen Orten setzen Einfädeln, wo es darauf ankommt.

Having said that, ich auch (gegebenenfalls) schaffen unveränderliche Typen, die auf Multi-Threading natürlich zugänglich sind -. Sowie einfacher zu sein im Allgemeinen zur Vernunft über

Folgen Sie die prinicple von „so einfach wie möglich, aber nicht einfacher.“ In Abwesenheit eine Anforderung, sollten Sie nicht machen sie Thread-sicher. Dies würde so sein spekulativ, und wahrscheinlich nicht erforderlich. Thread-sichere Programmierung fügt viel mehr Komplexität zu Ihren Klassen, und wird wahrscheinlich macht sie weniger performant aufgrund Synchronisationsaufgaben.

Sofern nicht ausdrücklich angegeben, dass ein Objekt Thread-sicher, die Erwartung ist, dass es nicht ist.

Ich persönlich würde nur Klassen entwerfen, die „thread-safe“, wenn nötig sind - auf dem Prinzip der Optimierung nur bei Bedarf. Sun zu haben scheint die gleiche Art und Weise mit dem Beispiel der Single-Threaded-Sammlungen Klassen gegangen.

Es gibt jedoch einige gute Grundsätze, die Sie so oder so wird helfen, wenn Sie ändern entscheiden:

  1. Das Wichtigste: denken, bevor Sie synchronisieren. Ich hatte mal einen Kollegen, die Sachen zu synchronisieren verwendet, um „nur für den Fall - schließlich besser synchronisiert wird, nicht wahr?“ Das ist falsch, und war eine Ursache für mehr Deadlock Fehler.
  2. Wenn Sie Ihre Objekte unveränderlich sein können, machen sie unveränderlich. Dies wird nicht nur mit Threading hilft, werden ihnen helfen, sicher in Mengen verwendet werden, als Schlüssel für Karten usw.
  3. Halten Sie Ihre Objekte so einfach wie möglich. Jeder sollte im Idealfall tun nur einen Job. Wenn Sie jemals finden Sie können den Zugang zu der Hälfte der Mitglieder synchronisieren, dann sollten Sie möglicherweise das Objekt in zwei Teile gespalten.
  4. Lernen java.util.concurrent und es verwenden, wann immer möglich. Deren Code wird besser, schneller und sicherer als Ihr (oder von mir) in 99% der Fälle.
  5. Lesen Sie Concurrent Programming in Java , es ist toll!

So wie eine Randbemerkung: Die Synchronisation = Thread-Sicherheit. Auch so können Sie nicht gleichzeitig Daten ändern, aber Sie könnten es gleichzeitig lesen. So halten Sie das Java-Speichermodell im Auge, wo bedeuten Synchronisationsdaten machen zuverlässig in allen Themen, nicht nur die gleichzeitige Änderung den es zu schützen.

Und ja, meiner Meinung nach Thread-Sicherheit hat in von Anfang an gebaut und es hängt von der Anwendungslogik, wenn Sie von Concurrency Handhabung müssen. Nie etwas annehmen und selbst wenn Ihr Test scheint in Ordnung zu sein, Rennbedingungen schlafen Hunde.

fand ich die JCIP Anmerkungen sehr nützlich, welche Klassen sind Thread-sicher zu erklären. Mein Team annotiert unsere Klassen als @ThreadSafe , < a href = "http://www.javaconcurrencyinpractice.com/annotations/doc/net/jcip/annotations/NotThreadSafe.html" rel = "nofollow noreferrer"> @ NotThreadSafe oder @ Immutable . Das ist viel klarer als Javadoc lesen zu müssen, und FindBugs hilft uns, Verletzungen des @Immutable zu finden und @ GuardedBy Verträge zu.

Sie sollten unbedingt wissen, welche Segmente des Codes mit mehreren Threads sein werden und welche nicht.

ohne die Möglichkeit, den Bereich der multithreadedness in einen kleinen, kontrollierbaren Abschnitt zu konzentrieren, werden Sie keinen Erfolg haben. Die Teile Ihrer App, die Multi-Thread-bedürftig sind sorgfältig übergegangen werden, vollständig analysiert, verstanden und für eine Multi-Threaded-Umgebung angepasst.

Der Rest nicht und daher macht es Thread-sicher eine Verschwendung wäre.

Zum Beispiel mit dem Swing-GUI, Sun habe gerade beschlossen, dass nichts davon mit mehreren Threads wäre.

Oh, und wenn jemand nutzt Ihre Klassen -. Es ist an sie, um zu gewährleisten, wenn es in einem Gewindeabschnitt ist dann macht es thread

So kam zunächst mit THREAD Sammlungen aus (nur). das Problem ist, kann THREAD nicht un-THREAD (für Leistungszwecke) hergestellt werden. So, jetzt kamen sie mit un-Thread-Versionen mit Wrapper aus, um sie THREAD. In den meisten Fällen sind die Wrapper nicht notwendig - davon ausgehen, dass, wenn Sie die Fäden selbst erstellen, dass Ihre Klasse nicht THREAD sein muss - aber DOKUMENT es in dem javadocs

.

Hier ist mein persönlicher Ansatz:

  • Erstellen Sie Objekte und Datenstruktur unveränderlich , wo immer Sie können. Das ist eine gute Praxis im Allgemeinen und wird automatisch Thread-sicher. Problem gelöst.
  • Wenn Sie auf ein Objekt machen wandelbar dann normalerweise Sie versuchen, sich nicht die Mühe, um es sicher zu machen fädeln . Die Begründung dafür ist einfach: Wenn Sie änderbaren Zustand haben, dann Verriegelung / Steuerung nicht sicher von einer einzigen Klasse behandelt werden. Selbst wenn Sie alle Methoden synchronisieren, bedeutet dies nicht Thread-Sicherheit garantieren. Und wenn Sie die Synchronisierung zu einem Objekt hinzufügen, die immer nur in einem Singlethread-Kontext verwendet werden, dann haben Sie nur unnötigen Aufwand hinzugefügt. So könnte man genauso gut es den Anrufer / Benutzer überlassen zu implementieren, was Verriegelungssystem notwendig ist.
  • Wenn Sie eine höhere Ebene öffentliche API bieten dann implementieren, was Verriegelung benötigt, um Ihre API-Gewinde sicher zu machen. Für höhere Level-Funktionalität ist der Aufwand für die Thread-Sicherheit ziemlich trivial, und die Benutzer werden Sie auf jeden Fall danken. Eine API mit komplizierter Gleichzeitigkeit Semantik, die die Benutzer um zu arbeiten brauchen, ist keine gute API!

Dieser Ansatz hat mich auch im Laufe der Zeit bedient: Sie die gelegentliche Ausnahme machen müssen können aber im Durchschnitt ist es ein sehr guter Anfang

Wenn Sie möchten, folgen, was Sun in der Java-API haben, können Sie einen Blick auf die Sammlung Klassen nehmen. Viele gemeinsame Sammelklassen sind nicht Thread-sicher, aber haben Thread-sichere Pendants. Laut Jon Skeet (siehe Kommentare), viele der Java-Klassen waren ursprünglich Thread-sicher, aber sie waren Entwickler nicht profitieren, so haben einige Klassen jetzt zwei Versionen - ein Wesen Thread-sicher und die andere Thread-sicher nicht

Mein Rat ist, nicht der Code Thread-sicher zu machen, bis Sie zu haben, denn es gibt einige Overhead mit Thread-Sicherheit beteiligt ist. Ich denke, das fällt in die gleiche Kategorie wie Optimierung -. Sie es nicht tun, bevor Sie müssen

Entwurf separat die Klassen von mehreren Threads zu verwenden und zu dokumentieren andere, die nur von einzelnen Thread verwendet werden.

Single Gewinde diejenigen sind viel einfacher, mit zu arbeiten.

, um die Multi-Thread-Logik Trennung hilft die Synchronisation richtig zu machen.

"Always" ist ein sehr gefährliches Wort in der Software-Entwicklung ... Entscheidungen wie diese sind "immer" situationsabhängig.

Rennbedingungen zu vermeiden, sperren auf nur ein Objekt - Beschreibungen von Rennbedingungen lesen ermüdend und Sie werden feststellen, dass Cross-Schlösser entdecken (Race-Bedingung ist eine falsche Bezeichnung - Rennen dort zu stoppen kommt) sind immer eine Folge von zwei + Threads versuchen, zu sperren, auf zwei + Objekten.

Machen Sie alle Methoden synchronisiert und Tests durchführen - für jede reale Welt Anwendung, die hat tatsächlich zu behandeln die Probleme synchronisieren ein klein Kosten. Was sie nicht sagen, ist, dass die ganze Sache tut Aussperrung auf 16-Bit-Zeigertabellen ... an diesem Punkt sind Sie äh, ...

So halten Sie Ihre Burger flippin Lebenslauf‘Strom.

  

Wenn ich Klassen erstellen, die nur im Moment in einem einzigen Thread verwendet werden, sollte ich machen sie thread-safe

Es ist nicht notwendig für eine Klasse von einem Thread zu selbst Thread-sicher für das Programm als Ganze verwendeten Thread-sicher zu sein. Sie können sicher Objekte nicht „thread-safe“ Klassen zwischen Threads , wenn teilen sie durch entsprechende Synchronisation geschützt sind. So gibt es keine Notwendigkeit, eine Klasse selbst Thread-sicher zu machen, bis diese deutlich.

Allerdings Multi-Threading ist von grundlegender Bedeutung (Architektur) Wahl in einem Programm. Es ist nicht wirklich etwas, als nach Gedanken hinzufügen . So sollten Sie wissen von Anfang an, die Klassen müssen Thread-sicher sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top