Ist der PrintWriter-Thread eines Java-Sockets sicher?

8

Also, ich habe zwei Threads.

Thread man verwaltet die Clientverbindungen. (Es gibt nur einen Client und einen Server) Ich nenne es meinen Server-Thread.

Thread two verwaltet das Senden von Nachrichten an den Client. Ich nenne es meinen Nachrichtenprozessor-Thread.

Thread eins ist verantwortlich, unter anderem regelmäßig einen Heartbeat an den Client zu senden.

Beim Programmieren nahm ich an, dass die Sockets nicht Thread-sicher waren, aber die Puffer waren, und solange ich separate Puffer für die Server- und Prozessor-Threads verwendete, würde es mir gut gehen.

Ich habe auch angenommen, dass der "PrintWriter" analog zum Socket-Puffer in Java ist.

Unter diesen Annahmen habe ich diese Funktion geschrieben, um einen Herzschlag zu senden:

%Vor%

Der andere Thread, der "Prozessor", macht etwas Ähnliches, indem es:

%Vor%

Auf diese Weise würde ich jedes Mal einen neuen "Puffer" erstellen, wenn ich einen Herzschlag senden wollte, und meine Nachrichten würden niemals überschrieben.

Leider scheint das nicht der Fall zu sein. Und ich bekomme eine Nachricht wie folgt durch die Leitung:   dsgdsbHEARTBEAT # sdg

Dies verursacht später einen Core-Dump.

Hier sind meine Fragen:

1) Sockets sind natürlich nicht threadsicher, aber sind die PrintWriter, die ich von ihnen bekomme, threadsicher? Oder gibt es nur den gleichen PrintWriter zurück?

2) Was ist analog zum Socket-Buffer in Java? Wie sollte ich über dieses Problem nachdenken?

3) Wie mache ich es so, dass diese Threads nicht in den gleichen Puffer auf dem Socket schreiben?

    
Alex 03.04.2009, 14:53
quelle

2 Antworten

10

Es ist ein schlechtes Design, diese multiplen PrintWriter s im selben Stream zu haben. Wirklich wollen Sie mindestens das Objekt, das sie ruft, synchronisiert werden (oder Thread beschränkt).

Nehmen wir jedoch an, Sie möchten mehrere PrintWriter s:

Erstes Problem: Writer s benutzt this nicht als Sperre. PrintWriter und BufferedWriter verwenden standardmäßig Writer , mit denen sie als Sperre konstruiert sind. Dies ist offensichtlich vollständig gebrochen. Sie sollten die Writer -Sperre verwenden, nicht die Writer selbst. Ein einfacher Fehler, da das Sperren eines Features von Object die Sicherheit des statischen Typs beseitigt. Sie müssen also ein PrintWriter mit dem Socket OutputStream (oder einem anderen gemeinsamen Objekt) als Sperre konstruieren.

Zweitens haben wir eine Pufferung innerhalb von PrintWriter . So kommt das Ende eines Puffers, die Hälfte wird geschrieben und die Hälfte wartet auf den nächsten Schreibvorgang. Um dies zu verhindern, sperren Sie entweder eine print und flush extern oder verwenden Sie die automatische Spülung und fügen Sie ein neues Zeilenzeichen hinzu.

Es ist also nicht sinnvoll threadsicher, aber Sie können es hacken. Oder Sie können ein besseres Design verwenden.

    
Tom Hawtin - tackline 03.04.2009, 15:21
quelle
4

Sie brauchen eine Möglichkeit, dieselbe PrintWriter zwischen den Threads zu verwenden ( t1.writer == t2.writer , nicht nur PrintWriter s, die aus derselben OutputStream erstellt wurden). Mit dem gleichen PrintWriter werden alle Schreibvorgänge synchronisiert.

    
Chris Jester-Young 03.04.2009 14:58
quelle

Tags und Links