Frage

In Java ist jedes Objekt hat eine synchronisation überwachen.Ich denke also, die Implementierung ist ziemlich verdichtet im Begriff des Speicherverbrauchs und hoffentlich schnell.

Bei der Portierung dieser in C++ was sollte die beste Umsetzung für Sie.Ich denke, es muss etwas besser dann "pthread_mutex_init" oder ist die Objekt-overhead in java wirklich so hoch?

Edit:ich habe gerade überprüft, dass pthread_mutex_t auf Linux-i386 ist 24 bytes groß.Das ist riesig, wenn ich reservieren Sie den Platz für jedes Objekt.

War es hilfreich?

Lösung

Die Sun Hotspot JVM implementiert dünn Schlösser mit vergleichen und Swap . Wenn ein Objekt gesperrt ist, dann warten die wartenden Thread auf dem Monitor des Threads, das Objekt verriegelt. Das heißt, Sie benötigen nur eine schwere Sperre pro Faden.

Andere Tipps

In einem gewissen Sinne ist es schlimmer als pthread_mutex_init, eigentlich. Aufgrund der Java Warte / benachrichtigen Sie Art von Notwendigkeit eines gekoppelten Mutex und Zustandsgröße einen Monitor zu implementieren.

In der Praxis, wenn ein JVM Implementierung Sie jede einzelne plattformspezifische Optimierung im Buch jagen und anwenden, und dann einige neue erfinden, um Monitore, so schnell wie möglich zu machen. Wenn Sie nicht eine wirklich teuflische Aufgabe, das tun können, sind Sie auf jeden Fall nicht auf der Garbage Collection zu optimieren; -)

Eine Beobachtung ist, dass nicht jedes Objekt benötigt einen eigenen Monitor haben. Ein Objekt, das derzeit nicht synchronisiert ist nicht brauchen. So kann die JVM einen Pool von Monitoren erstellen, und jedes Objekt kann nur ein Zeigerfeld hat, die eigentlich in, wenn ein Thread gefüllt will auf dem Objekt synchronisieren (mit einer plattformspezifischen atomaren Vergleichs- und Auslagerungsoperation, zum Beispiel). So sind die Kosten der Monitor Initialisierung muss nicht auf die Kosten der Objekterstellung hinzuzufügen. Angenommen, den Speicher bereits geklärten, Objekterzeugung kann sein: ein Zeiger dekrementieren (plus irgendeine Art von Grenzen zu überprüfen, mit einer vorhergesagten-falschen Verzweigung zu dem Code, der ausgeführt wird gc und so weiter); in der Art füllen; nennt den meist abgeleiteten Konstruktor. Ich glaube, Sie können für den Konstruktor von Object arrangieren nichts zu tun, aber natürlich viel hängt von der Implementierung.

In der Praxis ist die durchschnittliche Java-Anwendung nicht zu einem beliebigen Zeitpunkt auf sehr viele Objekte zu synchronisieren, so Monitor-Pools sind potenziell eine riesige Optimierung in der Zeit und Speichern.

Ich bin mir nicht sicher, wie Java funktioniert es, aber .NET nicht halten Sie den mutex (oder analog - die Struktur, hält es heißt "syncblk" dort) direkt in das Objekt.Vielmehr hat eine Globale Tabelle der syncblks und Objektreferenzen seine syncblk, die durch den index in dieser Tabelle.Des weiteren werden Gegenstände nicht bekommen syncblk, sobald Sie geschaffen sind, sondern die erstellt wird, auf die Nachfrage auf dem ersten Sperre.

Ich gehe davon aus (beachten Sie, ich weiß nicht, wie es tatsächlich tut Sie!) es verwendet Atomare compare-and-exchange verknüpfen Sie das Objekt und seine syncblk in einer thread-sicheren Weise:

  1. Überprüfen Sie die versteckte syncblk_index Feld der Objekt-für 0.Wenn es nicht 0 ist, sperren Sie es und gehen Sie, sonst...
  2. Erstellen Sie eine neue syncblk in der globalen Tabelle, um den index für es (global sperren werden/veröffentlicht hier, wie erforderlich).
  3. Vergleich-und-Austausch-schreiben es in Objekt selbst.
  4. Wenn der Vorherige Wert war 0 (davon ausgehen, dass 0 kein Gültiger index, und ist der Anfangswert für die versteckte syncblk_index Feld unserer Objekte), unsere syncblk Schöpfung war, nicht bestritten.Lock auf es und fahren Sie Fort.
  5. Wenn der Vorherige Wert nicht 0, dann jemand anderes hatte bereits ein syncblk und verknüpft es mit dem Objekt, während wir schufen uns, und wir haben der index der syncblk jetzt.Entsorgen Sie die, die wir gerade erstellt haben, und sperren Sie auf die eine, die wir erhalten haben.

Damit der overhead pro Objekt ist 4 bytes (unter Annahme von 32-bit-Indizes in syncblk Tabelle) im besten Fall, aber für größere Objekte, die tatsächlich gesperrt worden.Wenn Sie nur selten im Schloss auf den Objekten, dann wird dieses Schema sieht aus wie eine gute Möglichkeit zur Senkung der Ressourcennutzung.Aber wenn Sie benötigen, zu sperren auf die meisten oder alle Ihre Objekte schließlich, speichern Sie einen mutex, der direkt in das Objekt könnte schneller sein.

Sicherlich brauchen Sie nicht einen solchen Monitor für alle Objekt!

Wenn Sie von Java auf C ++ zu portieren, kommt es mir als eine schlechte Idee, einfach kopieren alles blind. Die beste Struktur für Java ist nicht das gleiche wie die am besten für C ++, nicht zuletzt, weil Java Garbage Collection und C ++ hat dies nicht tut.

Fügen Sie einen Monitor auf nur diejenigen Objekte, die es wirklich brauchen. Wenn nur dann einige Instanzen eines Typs Notwendigkeit Synchronisation ist es nicht so schwer, eine Wrapper-Klasse zu erstellen, die den Mutex enthält (und möglicherweise Zustandsgröße), die für die Synchronisation. Wie andere schon gesagt haben, eine Alternative ist es, einen Pool von Synchronisationsobjekten mit Mitteln einer für jedes Objekt der Wahl zu verwenden, wie zum Beispiel eines Hash-Wert des Objekts Adresse des Arrays verwendet wird.

ich die Boost-Thread-Bibliothek verwenden würde, oder die neuen C ++ 0x-Standard Thread-Bibliothek für die Portabilität, anstatt mich auf der Plattform Besonderheiten bei jeder Umdrehung. Boost.Thread unterstützt Linux, Mac OS X, win32, Solaris, HP-UX und andere. Mein Implementierung der C ++ 0x derzeit Bibliothek Thread nur Windows und Linux unterstützt, aber auch andere Implementierungen werden zur Verfügung zu gegebener Zeit.

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