Teóricamente, es posible que la lectura esté en caché. Nada en el modelo de memoria de Java impide eso.
Prácticamente, esto es muy poco probable que suceda (en su caso particular). La pregunta es si JVM puede optimizar en una llamada a método.
read #1
method();
read #2
Para JVM a la razón de que leer # 2 se puede volver a utilizar el resultado de la lectura # 1 (que puede ser almacenado en un registro de la CPU), debe estar seguro de que method()
no contiene acciones de sincronización. Esto es generalmente imposible, a menos que method()
esté en línea, y JVM puede ver desde el código sin formato que no hay sincronización/volátil u otras acciones de sincronización entre la lectura # 1 y la lectura # 2; entonces puede eliminar con seguridad la lectura n. ° 2.
En su ejemplo, el método es Thread.sleep()
. Una forma de implementarlo es con el bucle ocupado durante ciertos tiempos, dependiendo de la frecuencia de la CPU. Entonces JVM puede alinearlo, y luego eliminar la lectura # 2.
Pero, por supuesto, tales implementación de sleep()
es poco realista. Por lo general, se implementa como un método nativo que llama kernel OS. La pregunta es si JVM puede optimizar a través de un método nativo.
Incluso si JVM tiene conocimiento del funcionamiento interno de algunos métodos nativos, por lo tanto puede optimizarlos, es improbable que sleep()
se trate de esa manera. sleep(1ms)
requiere millones de ciclos de CPU para regresar, realmente no tiene sentido optimizarlo para guardar algunas lecturas.
-
Esta discusión revela que el mayor problema de las razas de datos - se necesita mucho esfuerzo para razonar sobre ello. Un programa no es necesariamente incorrecto, si no está "correctamente sincronizado", sin embargo, demostrar que no está mal no es una tarea fácil. La vida es mucho más simple, si un programa está sincronizado correctamente y no contiene datos de raza.
No puedo decir 100%, pero parece que la lectura no sincronizada del campo no volátil no está garantizada para leer el valor más reciente de 'invoc' (a pesar de que las escrituras * * se vacían debido a la palabra clave 'synchronized' en el método' increment() '). Sin embargo, no conoce el modelo de memoria Java lo suficiente como para decirlo con seguridad. – dlev
@dlev Esa es, más o menos, la pregunta;) – krosenvold
Estaba a punto de responder: "¡Siempre me ha funcionado!". Pero también se encontró http://stackoverflow.com/questions/1006655/are-java-primitive-ints-atomic-by-design-or-by-accident que dicen "Sí" para las entradas, y "Quizás" para las que son largas y dobles. . –