¿Es seguro el hilo estático int si se incrementa en un solo método?

Quiero rastrear getVariableAndLogAccess(RequestInfo requestInfo)usando el código a continuación. ¿Será seguro para subprocesos si solo estos dos métodos acceden a la variable? ¿Cuál es la forma estándar de hacer que sea seguro para subprocesos?

public class MyAccessLog(){

    private int recordIndex = 0;
    private int variableWithAccessTracking = 42; 
    private final Map<Integer, RequestInfo> requestsLog = new HashMap<>();
    public int getVariableAndLogAccess(RequestInfo requestInfo){
        Integer myID = recordIndex++;
        int variableValue = variableWithAccessTracking;
        requestInfo.saveValue(variableValue);
        requestLog.put(myID, requestInfo);
        return variableValue;
     }
     public void setValueAndLog(RequestInfo requestInfo, int newValue){
        Integer myID = recordIndex++;
        variableWithAccessTracking = variableValue;
        requestInfo.saveValue(variableValue);
        requestLog.put(myID, requestInfo);
     }

/*other methods*/
}
Respuesta 1

¿Será seguro para subprocesos si solo estos dos métodos acceden a la variable?

No.

Por ejemplo, si dos hilos llaman setValueAndLog, pueden terminar con el mismo myIDvalor.

¿Cuál es la forma estándar de hacer que sea seguro para subprocesos?

Debería reemplazarlo intcon un AtomicInteger , usar un bloqueo o un bloque sincronizado para evitar modificaciones concurrentes.

Como regla general, usar una variable atómica como la mencionada anteriormente AtomicIntegeres mejor que usar bloqueos ya que los bloqueos involucran al sistema operativo. Llamar al sistema operativo es como traer a los abogados: es mejor evitar ambos para las cosas que puede resolver usted mismo.

Tenga en cuenta que si usa bloqueos o bloques sincronizados, tanto el configurador como el getter deben usar el mismo bloqueo. De lo contrario, se podría acceder al getter mientras el setter todavía está actualizando la variable, lo que lleva a errores de concurrencia.

Respuesta: 2

¿Será seguro para subprocesos si solo estos dos métodos acceden a la variable?

No

Intuitivamente, hay dos razones:

  • Un incremento consiste en una lectura seguida de una escritura. El JLS no garantiza que los dos se realizarán como una operación atómica. Y de hecho, tampoco las implementaciones de Java hacen eso.

  • Los sistemas multinúcleos modernos implementan el acceso a la memoria con cachés de memoria local rápidos y memoria principal más lenta. Esto significa que no se garantiza que un hilo vea los resultados de las escrituras de memoria de otro hilo ... a menos que haya instrucciones apropiadas de "barrera de memoria" para forzar las escrituras / lecturas de la memoria principal.

    Java solo insertará estas instrucciones si el modelo de memoria dice que es necesario. (Porque ... ¡ralentizan el código!)

Técnicamente, el JLS tiene un capítulo completo que describe el modelo de memoria de Java, y proporciona un conjunto de reglas que le permiten razonar si la memoria se está utilizando correctamente. Para el material de nivel superior, puede razonar en función de las garantías proporcionadas por AtomicInteger, etc.

¿Cuál es la forma estándar de hacer que sea seguro para subprocesos?

En este caso, puede usar una AtomicIntegerinstancia o puede sincronizar usando un bloqueo de objeto primitivo (es decir, la synchronizedpalabra clave) o un Lockobjeto.

Respuesta: 3

Mi programa Java realiza extracción de texto en archivos RTF utilizando RTFEditorKit. Algunos de los archivos RTF contienen caracteres cirílicos (ruso) y, según la versión RTF, el texto extraído es ...

Estoy revisando las diferencias entre Struts1 y Strust2, descubrí que, un problema común en Struts 1 es programar en clases abstractas en lugar de interfaces. ¿Alguien podría dejarme ...

Tengo una lista de objetos que contiene diferentes tipos de objetos, pero una sola propiedad es común entre todos. La lista contiene objetos de clase de campo, clase de botón, clase de página, etc. pero una propiedad es ...

Actualización: Respondí mi propia pregunta aquí: Escanear classpath / modulepath en tiempo de ejecución en Java 9 - [Pregunta anterior - obsoleta:] En el sistema de módulos Java 9, puede encontrar módulos del sistema usando Set <...