2009-10-25 8 views
6

Leyendo algunos hilos (common concurrency problems, volatile keyword, memory model) Estoy confundido sobre problemas de simultaneidad en Java.Si más de un hilo puede acceder a un campo ¿debería marcarse como volátil?

Tengo un montón de campos a los que se accede por más de un hilo. ¿Debería revisarlos y marcarlos como volátiles?

Cuando se construye una clase No estoy al tanto de si varios subprocesos tendrán acceso a ella, por lo que seguramente no es seguro dejar que cualquier campo no ser volátil, por lo que a mi entender hay muy pocos casos en que no lo utilizaría . ¿Es esto correcto?

Para mí, esto es específico para las JVM de la versión 1.5 y posteriores, pero no me siento limitado a responder sobre mi configuración específica.

Respuesta

3

Si se accede a un campo por varios hilos, debe ser volatile o final, o acceder solo con bloques sincronizados. De lo contrario, los valores asignados pueden no ser visibles para otros hilos.

Una clase tiene que estar específicamente diseñada para el acceso concurrente por varios hilos. Simplemente marcar campos volátiles o finales no es suficiente para la seguridad de la hebra. Hay problemas de consistencia (atomicidad de cambios en varios campos), las preocupaciones sobre la señalización entre hilos (por ejemplo utilizando wait y notify), etc.

lo tanto, es más seguro suponer que un objeto debe ser visible solamente a una un solo hilo a menos que se documente lo contrario. No es necesario hacer que todos sus objetos sean seguros para subprocesos, y es costoso — en términos de velocidad de software, pero más importante aún, en términos de gasto de desarrollo.

En su lugar, el software debe diseñarse de modo que los hilos concurrentes interactúen entre sí lo menos posible, preferiblemente de ninguna manera. Los puntos donde interactúan deben estar claramente identificados para poder diseñar los controles de concurrencia adecuados.

4

Bueno, usted ha leído esas otras preguntas y supongo que ha leído las respuestas ya, así que voy a resaltar algunos puntos clave:

  1. van a cambiar? de lo contrario, no necesita el
  2. volátil
  3. En caso afirmativo, ¿el valor de un campo está relacionado con otro? En caso afirmativo, vaya al punto 4
  4. ¿cuántos hilos lo cambiarán? si solo 1, entonces volátil es todo lo que necesita
  5. si la respuesta al número 2 es "no" o más de un hilo va a escribir en él, entonces solo volátil es no es suficiente, es probable que necesite sincronizar el acceso

Agregado:
Si la referencia de campo de un objeto, entonces tendrá campos propios y todos aquellos consideración también se aplica a estos campos.

1

La respuesta corta es no. Temas de enhebrado requieren más pensamiento y planificación que esto. Consulte this para conocer algunas limitaciones sobre cuándo la volatilidad ayuda a enhebrar y cuándo no. La modificación de los valores debe sincronizarse correctamente, pero muy típicamente la modificación requiere el estado de más de una variable a la vez. Digamos, por ejemplo, que tiene una variable y desea cambiarla si cumple con un criterio. La lectura de la matriz y la escritura en la matriz son instrucciones diferentes, y deben sincronizarse juntas. Volátil no es suficiente.

Considere también el caso donde la variable hace referencia a un objeto mutable (digamos una matriz o una colección), y luego la interacción con ese objeto no será segura solo porque la referencia sea volátil.

2

Si tiene que preguntar, use bloqueos. volatile puede ser útil en algunos casos, pero es muy, muy difícil hacerlo bien. Por ejemplo:

class Foo { 
    private volatile int counter = 0; 
    int Increment() { 
    counter++; 
    return counter; 
    } 
} 

Si dos hilos corren Increment(), al mismo tiempo, es posible que el resultado sea counter = 1. Esto se debe a que la computadora primero recuperará counter, agrega uno y luego lo guarda de nuevo. Volátil solo obliga a guardar y cargar en un orden específico relativo a otras declaraciones.

Tenga en cuenta que synchronized por lo general evita la necesidad de volatile - si todos los accesos a un determinado campo están protegidos por el mismo monitor, no se necesitarán volatile.

Usar volatile para hacer algoritmos sin cerradura es muy, muy difícil; cúmplase al synchronized a menos que tenga pruebas fehacientes de que ya es demasiado lento y haya realizado un análisis detallado del algoritmo que planea implementar.

+0

Para este caso de uso en particular, consulte AtomicInteger, en lugar de utilizar 'synchronized' usted mismo. – erickson

+1

De hecho. Solo quería demostrar las trampas de usar ciegamente 'sincronizado' sin entender exactamente lo que hace y no proporciona – bdonlan

Cuestiones relacionadas