2009-04-03 21 views
8

Entonces, tengo dos hilos.¿Es seguro un subproceso PrintWriter de socket Java?

El hilo uno gestiona las conexiones del cliente. (Solo hay un cliente y un servidor)
Lo llamo mi hilo de servidor.

El subproceso dos gestiona el envío de mensajes al cliente. Lo llamo mi hilo de procesador de mensajes.

El hilo uno es responsable, entre otras cosas, de enviar un latido del corazón al cliente periódicamente.

Cuando programé, asumí que los sockets no eran seguros para subprocesos, pero los búferes sí, y siempre que utilizara búferes separados para el servidor y los hilos del procesador, estaría bien.

También he hecho la suposición de que la "PrintWriter" era análoga a la memoria intermedia de socket en Java.

Bajo estos supuestos escribí esta función para enviar un latido del corazón:

public void sendHeartBeat(){ 
     logger.info("Sending a hearbeat!"); 
     PrintWriter printWriter=null; 
     try { 
      printWriter = new PrintWriter(clientSocket.getOutputStream()); 
     } catch (IOException e) { 
      logger.info(e.toString()); 
     } 
     if(printWriter!=null){ 
      printWriter.print("HEARTBEAT#"); 
      printWriter.flush(); 
     } 
    } 

El otro hilo, el "procesador" hace algo similar, ya que hace:

printWriter=new PrintWriter(theServer.getClientSocket().getOutputStream()); 

De esta manera, Crearía un nuevo "buffer" cada vez que deseara enviar un latido, y mis mensajes nunca serían sobrescritos.

Desafortunadamente, este no parece ser el caso. Y me sale un mensaje que viene a través de la tubería de la siguiente manera: dsgdsbHEARTBEAT # SDG

Esto provoca un volcado de memoria más tarde.

Aquí están mis preguntas:

1) Los enchufes son, obviamente, no seguro para subprocesos, pero son los PrintWriters que recibo de ellos hilo de seguridad? ¿O solo está devolviendo el mismo PrintWriter?

2) ¿Qué es análogo al buffer de socket en Java? ¿Cómo debería pensar sobre este problema?

3) ¿Cómo puedo hacer para que estos hilos no escriban en el mismo buffer en el socket?

Respuesta

10

Es un diseño pobre para tener estos múltiples PrintWriter s en la misma corriente. Realmente desea al menos el objeto que las llama para sincronizarse (o enrutar confinado).

Sin embargo, suponiendo que por alguna razón te quiero múltiples PrintWriter s:

Primer problema: Writer s no utilizan this como la cerradura. PrintWriter y BufferedWriter de forma predeterminada ambos usan el Writer con el que están construidos como cerradura. Esto está obviamente completamente roto. Deben usar el candado Writer, no el Writer.Un error fácil dado que al bloquear una función de Object se elimina la seguridad del tipo estático. Por lo tanto, deberá construir un PrintWriter con el socket OutputStream (u otro objeto común) como el candado.

En segundo lugar, tenemos tampón dentro PrintWriter. Así que ven al final de un buffer, medio escrito y medio esperando la próxima escritura. Para evitar eso, bloquee externamente para combinar un print y flush, o use la función de limpieza automática y agregue un nuevo carácter de línea.

Por lo tanto, no es significativamente hilo seguro, pero puede hackearlo. O puedes usar un mejor diseño.

+0

Eché un vistazo a Java SE 1.6.0_31 src para esto. 'PrintWriter (Writer out)' finalmente llama 'Writer protegido (bloqueo de objetos)' y allí, 'Writer' asigna este 'bloqueo' a su 'bloqueo' interno que se usa en 'Writer' para la sincronización. Así que podrías pl explica por qué crees que el bloqueo está roto aquí? – shrini1000

+0

@ shrini1000 'PrintWriter' llama a' Writer (Object lock) 'con' super (out); '. Entonces 'lock' es' out', en lugar de 'out.lock'. (Este es un problema de implementación: parece que falta la especificación). –

+0

Este parece ser el caso en Java 8 - PrintWriter llama a super (out) y lock está fuera en lugar de out.lock. –

4

Necesita una forma de utilizar el mismo PrintWriter entre los hilos (t1.writer == t2.writer, no solo PrintWriter s creados a partir del mismo OutputStream). Con el mismo PrintWriter, todas las operaciones de escritura están sincronizadas.

+1

¿Está diciendo que los PrintWriters son seguros para subprocesos, pero OutputStreams no lo son? – Alex

+3

Creo que Chris dice que PrintWriter es seguro para la ejecución de subprocesos, pero dos en la misma secuencia no son seguros para subprocesos. Por lo tanto, usa uno. –

Cuestiones relacionadas