Pregunta

Estoy buscando en algún código heredado que tiene la siguiente idioma:

Map<String, Boolean> myMap = someGlobalInstance.getMap();
synchronized (myMap) {
    item = myMap.get(myKey);
}

La advertencia que recibo de inspecciones de código de Intelli-J es:

Synchronization on local variable 'myMap'

¿Es esta la sincronización apropiada y por qué?

Map<String, Boolean> myMap = someGlobalInstance.getMap();
synchronized (someGlobalInstance.getMap()) {
    item = myMap.get(myKey);
}
¿Fue útil?

Solución

La razón de que esto se marca como un problema se debe a que la sincronización de las variables locales suele ser una mala idea.

el objeto devuelto por someGlobalInstance.getMap() es siempre el mismo, entonces el bloque sincronizado de hecho utilizar el Monitor de que los objetos cuasi-global y el código produce el resultado esperado.

También estoy de acuerdo con la sugerencia de utilizar un envoltorio sincronizada, si sólo se necesita para sincronizar las llamadas get() / put() y no tiene ninguna grandes bloques sincronizados. Pero asegúrese de que el mapa es solamente accede a través de la envoltura o tendrá otra oportunidad para los insectos.

También tenga en cuenta que si someGlobalInstance.getMap() hace no devolver el mismo objeto todo el tiempo, entonces incluso el segundo ejemplo de código no funcionará correctamente, incluso podría ser peor que el código original ya que es posible sincronizar el un objeto diferente a la que se llama a get() sucesivamente.

Otros consejos

Creo que el código podría estar en buen estado, dependiendo de lo que hace el método getMap (). Si se mantiene una referencia a una instancia que tiene que ser compartida entre los hilos que tiene sentido. La advertencia es irrelevante ya que la variable local no se ha inicializado localmente.

Creo que sería mejor usar sincronizada envoltorio para su mapa

Alex es correcto en que la adición de un envoltorio sincronizada llamando Collections.synchronizedMap(Map) es un enfoque típico aquí. Sin embargo, si se toma este enfoque todavía puede haber situaciones en las que necesita sincronizada en la cerradura de la Map; p.ej. cuando se itera sobre el mapa.

Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<String, String>());

// Synchronized on map to prevent ConcurrentModificationException whilst iterating.
synchronized (syncMap) {
  for (Map.Entry<String, String> entry : syncMap.entrySet()) {
    // Do work
  }
}

En su ejemplo, la advertencia de IDEA puede ser ignorado, ya que es evidente que su variable local: map se recupera de otra parte (someGlobalInstance) en lugar de ser creado dentro del método, y puede por lo tanto potencialmente puede acceder desde otros hilos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top