2012-06-22 6 views
9

¿Qué opciones tengo para hacer que un hilo de ByteBuffer sea seguro? Se sabe que no es seguro para subprocesos ya que la posición de la caja fuerte, el límite y algunos (¿todos?) Dependen de este estado interno.Opciones para hacer que el hilo ByteBuffer de Java sea seguro

Para mis propósitos, será suficiente si varios hilos de lectura son seguros, pero para otros visitantes futuros me gustaría saber qué técnicas/trucos/trampas necesito saber para que sean completamente seguros para hilos.

Lo que tengo en mente:

  • Sincronización o el uso de bloqueos ReadWrite para todos los métodos. Probablemente el enfoque más lento (?)
  • Subclase de ByteBuffer y evitar persistencia de estado ligado a hilos como posición etc. Y lanzando excepciones en consecuencia para todos los métodos que necesiten usar el estado interno. Este sería el ayuno Pero, ¿hay trampas? (excepto que tendré que leer la memoria directamente mapeada en la memoria del montón ...)

¿Qué otros trucos podría utilizar? ¿Cómo podría, por ejemplo, implementar un "clonar bytes en lectura" con DirectBuffer - ¿es posible? ¿Sería posible dividir el ByteBuffer completo (ByteBuffer.slice) en una sola solución?

actualización: ¿Qué se entiende en este question con "duplicado (mientras sincronizada) para obtener una nueva instancia apunta a los mismos bytes asignados"

+1

Prefiero usar un modelo de actor en el que cualquier ByteBuffer se actualiza por un solo hilo (o es de solo lectura). La razón por la que hago esto es porque descubrí que la sobrecarga de la sincronización generalmente supera los beneficios de tener múltiples hilos. –

+0

gracias, peter! ¿Estás usando esto a través de una rebanada? o ¿cómo se accede a la misma información? – Karussell

+0

No uso un corte, en cambio uso un envoltorio que lo oculta todo (incluso el hecho de que estoy usando ByteBuffers y es posible que desee cambiar a Inseguro, que es un poco más rápido). La ventaja de usar un envoltorio es que puedes ocultar todo los detalles y acceda a su "matriz" de forma natural llamando a métodos. Esto es particularmente útil ya que tengo matrices con miles de millones de elementos que no caben en un solo ByteBuffer. –

Respuesta

11

un buffer de clase podría hacerse seguro para subprocesos ... en el sentido de que las operaciones individuales se sincronizaron correctamente, etcétera. Sin embargo, la API no está diseñada con múltiples hilos en mente, por lo que esto probablemente sea una pérdida de tiempo.

El problema básico es que las operaciones individuales en un Buffer son demasiado finas para ser la unidad de sincronización. Una aplicación no puede sincronizarse de forma significativa al nivel de las operaciones de obtención y colocación, o cambio de posición, etc. En términos generales, una aplicación necesita realizar secuencias de estas operaciones de forma atómica para sincronizarse de forma efectiva.

El segundo problema es que si sincroniza en un nivel fino, es probable que agregue gastos indirectos significativos en las llamadas a métodos. Dado que el punto de utilizar las API de la memoria tampón es hacer E/S de manera eficiente, esto frustra el propósito.


Si necesita sincronizar el acceso de subprocesos a un búfer compartido, es mejor utilizar la sincronización externa; p.ej. algo como esto:

synchronized (someLock) { 
     buffer.getByte(); 
     buffer.getLong(); 
     ... 
    } 

A condición de todas las discusiones que utilizan un tampón dado sincronizará correctamente (por ejemplo, utilizando el mismo objeto de bloqueo), no importa que el tampón no es seguro para subprocesos. La seguridad del subproceso se gestiona externamente al objeto del búfer, y de una manera más gruesa.


Como señalan los comentarios, también se puede utilizar ByteBuffer.slice() o buffer.asReadOnlyBuffer() para darle otro tampón con la existente como respaldo. Sin embargo, los javadocs no garantizan la seguridad del hilo en ninguno de los casos.De hecho, el javadocs para Buffer hacer esta declaración general:

Los tampones no son seguros para el uso de múltiples subprocesos simultáneos. Si un buffer debe ser utilizado por más de un hilo, el acceso al buffer debe controlarse mediante la sincronización adecuada.

+0

¿Podría comentar sobre el caso de búfer de solo lectura? – Karussell

+0

No creo que el caso de solo lectura simplifique las cosas , a menos que esté preparado para tratar el búfer como una matriz simple ... busque y use la matriz de respaldo directamente a través de 'array()'. Incluso entonces necesita alguna sincronización para asegurar que la memoria tenga acceso de manera consistente. –

+1

¿Cómo podría ser inconsistente cuando no write happen? también la matriz de respaldo no siempre existe – Karussell

Cuestiones relacionadas