2010-12-29 5 views
2

Ich habe Java Concurrency in Practice gelesen und bin mit dieser Frage: Wenn ich eine ConcurrentHashMap verwenden, welche Daten Nebenläufigkeit Probleme in Teil eins des Buches diskutiert muss ich mich noch Sorgen machen? Hier ein paar Beispiele von einem meiner Programme sind:Verwendung von ConcurrentHashMap beseitigt Datensichtbarkeitsprobleme?

1. Aktuelle Position eines Händlers (eine gemeinsame Ganzzahl, wobei ‚integer‘ ist der mathematische Begriff)

Diese Zahl stellt dar, was ein trader Objekt zur Zeit besitzt und definiert seinen Zustand. Es muss seine Position lesen, um zu wissen, was zu tun ist (schauen Sie, um eine neue Position zu beginnen oder die aktuelle zu verwalten). Trader Methoden laufen auf ihrem eigenen Thread.

Ein broker Objekt ist für die Einstellung der Position trader zuständig. Es wird die Position jedes Mal festlegen, wenn eine Order des Händlers gefüllt ist. Methoden laufen auf ihrem eigenen Thread.

Sowohl trader als auch broker sind im selben Paket enthalten. Die Position ist als Paket-Privat static ConcurrentHashMap implementiert. Die Schlüssel sind IDs der Händlerobjekte. Die Werte sind Ganzzahl.

Extern zum Paket ist die Anwendung. Es bringt die Positionen der Händler indirekt mit einem öffentlichen Getter zusammen.

Positionen ändern sich höchstens alle paar Minuten, so dass die broker die Karte nicht oft berührt. Die trader und Anwendung wird jedoch häufig gelesen. Außerdem haben wir oft mehrere Händler, die die Karte gleichzeitig lesen.

Also eine ConcurrentHashMap auf diese Weise verwenden, muss ich nicht über Sperren und Datensichtbarkeit arbeiten? Die ConcurrentHashMap kümmert sich um alles?

2. Der Markt (bid, fragt, zuletzt Preise)

So ziemlich die gleiche Situation wie Position, außer jetzt die broker wird sehr häufig die Preise aktualisieren (bis zu 10 aktualisiert eine Sekunde während der stark frequentierten Zeiten (normalerweise ein paar Mal pro Sekunde). Das trader und die Anwendung führen weiterhin häufig Lesevorgänge durch. Die Kartenschlüssel sind jetzt Codes, die angeben, welche Aktie oder Zukunft, und die Werte sind Objekte, die die Marktpreise halten.

Es scheint in Ordnung zu arbeiten, aber nachdem ich JCIP gelesen habe, merke ich, dass das Programm immer noch kaputt sein kann, wenn die Dinge nicht korrekt implementiert sind. Das Buch spricht über die ConcurrentHashMap, sagt mir aber nicht explizit, welche Probleme aus Teil I wir nicht mehr manuell lösen müssen. Es erscheint , dass ich in diesem Fall nichts synchronize haben muss. Ist das korrekt?

+1

Ich würde Sie ermutigen, Ihre Frage neu zu formulieren. Dies setzt voraus, dass jeder das Buch gelesen hat. Dies begrenzt die Anzahl der Antworten, die Sie erhalten. – Davidann

Antwort

2

So mit einem ConcurrentHashMap auf diese Weise, Ich habe nicht über Sperren und Datentransparenz zu arbeiten? Die ConcurrentHashMap kümmert sich um alles?

Dies hängt davon ab, was in der Karte ist, wenn ich lese sieht Ihr Beispiel richtig die Situation wie diese

static final ConcurrentMap<Integer,Integer> map = ... 

class Trader{ 

    public int doRead(){ 
     map.get(someId); 
    } 
} 
class Broker{ 
    public void doWrite(){ 
     map.put(someId,someValue); 
    } 
} 

Wenn das der Fall ist, dann sind alle ja die Gleichzeitigkeit ist gesorgt.

Wenn jedoch die Karte sieht aus wie

static final ConcurrentMap<Integer,Trader> map = .. 

    class Broker{ 
     public void doWrite(){ 
      map.get(someId).setPosition(somePosition); 
     } 
    } 

Dies ist nicht Thread-sicher, obwohl die ConcurrentHashMap Schlösser, wenn Sie setzen, die alle gleichzeitiger Zugriff von Objekten an dieser Stelle müssen ihre eigene Synchronisation behandeln.

+0

Also das Problem im zweiten Beispiel ist, dass wir den Broker eine Sperre erwerben, dann einen Alien-Aufruf an den Händler, der die Sperre für die gleiche Karte benötigt? – Pete

+0

Das Problem besteht darin, dass die Map Thread-sicher ist, aber alle veränderbaren Objekte in der Map nicht threadsicher sind. –

+2

@Pete, wie Peter Lawrey erwähnt - veränderbare Objekte sind nicht threadsicher, wenn sie nicht selbst korrekt synchronisiert sind. Sobald Sie in das CHM einsteigen, verlieren Sie neue Synchronisationspunkte (eine Lock-Erfassung). Alle CHM-Gets (naja, fast alle) erhalten niemals die Put-Sperre. Wenn also ein Feld eines Objekts, das die Map enthält, geändert wurde, sehen andere Threads diese Änderung möglicherweise nicht. –

3

Ja, ConcurrentHashMap kümmert sich um die Sichtbarkeit und Verriegelungs solange:

  • auf der Karte gespeicherten Werte unveränderlich sind. Scheint in Ihrer Beschreibung wahr zu sein, vorausgesetzt, dass Ihre Preise Objekte unveränderlich sind;
  • Sie haben keine Operationen auf der Karte, die atomar sein müssen und nicht als einzelne Aufrufe der Map-API ausgedrückt werden können. Wenn Sie beispielsweise eine Operation wie 'Wert aus Karte lesen, Berechnung ausführen und das Ergebnis zurück auf die Karte einfügen' als atomar verwenden möchten, müssen Sie während dieses Vorgangs die explizite Sperre beibehalten oder noch besser die Anwendung ändern Verwenden Sie atomare Operationen der Karten-API wie get/put/putIfAbsent.
2

Wenn Sie nicht über mehr als 100.000 Updates/Lesevorgänge pro Sekunde sprechen, würde ich nicht in Betracht ziehen, mehrere Threads zu verwenden. Der Grund dafür ist, dass thread-safe Komponenten um ein Vielfaches länger dauern als nicht-taugliche Komponenten. Wenn also eine Komponente 5x länger dauert, um threadsicher zu sein, müssen Sie mehr als 5 Threads gleichzeitig verwenden, um den Break Even zu erreichen.

Mehrere Threads sind viel nützlicher, wenn Sie relativ teure Operationen durchführen müssen. Das Aktualisieren einer Position oder eines Preises ist viel effizienter als ein Thread.

+0

In diesem Fall segmentierte der separate Code den Code logisch und erleichterte die Pflege und Entwicklung. Es gibt nur ein bisschen gemeinsame, veränderbare Daten, also denke ich, dass der Kompromiss es wert ist. Geschwindigkeit ist kein großes Problem, da ich nicht an dem Wahnsinn teilnehme, der als "HFT" bekannt ist. – Pete

+0

Wenn Geschwindigkeit kein großes Problem ist, würde ich eine hohe Sperre für die Sammlung und alles darin verwenden. (und stellen Sie sicher, dass der Zugriff so schnell wie möglich ist, keine Aufrufe an IO usw.) Dies ist die einfachste Option. –

+0

Korrekt, die Kosten für den Threadkontextwechsel sind beträchtlich. Sie müssen also sicherstellen, dass die anfallenden Arbeiten ausreichend kostspielig sind, um sich zu lohnen. Hier ist ein interessanter Link, der die tatsächlichen Kosten beschreibt: http://blog.tsunanet.net/2010/11/how-long-does-it-take-to-make-context.html –

Verwandte Themen