Pregunta

Esta publicación de blog muestra una forma de implementar un mutex por idioma de id de cadena. Los identificadores de cadena utilizados son para representar identificadores HttpSession.

  1. ¿Por qué necesitamos ajustar una WeakReference alrededor de las instancias de Mutex? ¿No es mejor crear un Mapa desde String? & Gt; Mutex?
  2. ¿Por qué necesitamos llamar a put dos veces?

    public Mutex getMutex( String id )
    {                                  
        Mutex key = new MutexImpl( id );
        synchronized( mutexMap )
        {
            WeakReference<Mutex> ref = mutexMap.get( key );
            if( ref == null )
            {
                mutexMap.put( key, new WeakReference<Mutex>( key ) );
                return key;
            }
            Mutex mutex = ref.get();
            if( mutex == null )
            {
                mutexMap.put( key, new WeakReference<Mutex>( key ) );
                return key;
            }
            return mutex;
        }
    }
    
¿Fue útil?

Solución

Loop y Bruno Conde lo he cubierto bastante, pero desde que escribí ese código ...

El objetivo del diseño era evitar que el usuario llamara a un mecanismo de liberación: el mutex es elegible para la recolección de basura cuando el usuario ya no hace referencia a él.

  

¿Por qué necesitamos envolver una referencia débil?   alrededor de las instancias de Mutex?

El mapa es un WeakHashMap :

private final Map mutexMap = new WeakHashMap();

Este mapa se usa para mantener una referencia al mutex, pero si usa el mismo objeto para la clave y el valor, el objeto no es elegible para la recolección de basura. Javadoc:

  

Nota de implementación: los objetos de valor   en un WeakHashMap son propiedad de ordinarios   referencias fuertes Por lo tanto, se debe tener cuidado   tomado para asegurar que los objetos de valor   no se refieren fuertemente a sus propias claves,   ya sea directa o indirectamente, ya que   eso evitará que las llaves sean   descartado. Tenga en cuenta que un objeto de valor   puede referirse indirectamente a su clave a través de   el propio WeakHashMap; eso es un   objeto de valor puede referirse fuertemente   algún otro objeto clave cuyo asociado   objeto de valor, a su vez, se refiere fuertemente   a la clave del primer objeto de valor.   Una forma de lidiar con esto es envolver   se valoran dentro de   WeakReferences antes de insertar, como   en: m.put (clave, nuevo   WeakReference (valor)), y luego   desenvolviendo en cada get.


  

¿No es así?   mejor simplemente crear un Mapa desde   Cadena - > Mutex?

¿Cuándo se recolectará ese valor de cadena? ¿Se pasa siempre la misma referencia? Tiene interno () ha sido llamado? Si llamo interno, ¿cuánto tiempo durará la cadena? Si una cadena era la clave, el mutex podría no ser elegible para la recolección de basura mucho después de que no haya necesidad de mantener una referencia a él.


  

¿Por qué necesitamos llamar a put dos veces?

Hay dos casos para manejar hasta que el método pueda obtener una referencia fuerte al mutex en el mapa:

  • el WeakReference tiene sido recolectado basura (o nunca estuvo allí en primer lugar)
  • el contenido de WeakReference es basura recolectada después de que se ha adquirido la referencia a ella

put solo se invocará una vez; el método vuelve inmediatamente después.

(La WeakReference podría reutilizarse en el segundo puesto, pero no veo que sea una mejora significativa).


Por supuesto, si alguien puede encontrar fallas en el código, avíseme y con gusto lo corregiré. Además, las pruebas unitarias intentan verificar que la implementación no tenga fugas, así que siéntase libre de modificar el código y ver qué sucede cuando ejecuta las pruebas.

Otros consejos

Los objetos de valor en un WeakHashMap se encuentran en referencias fuertes comunes. Por lo tanto, se debe tener cuidado para garantizar que los objetos de valor no se refieran fuertemente a sus propias claves, ya sea directa o indirectamente, ya que eso evitará que las claves se descarten. Tenga en cuenta que un objeto de valor puede referirse indirectamente a su clave a través del propio WeakHashMap; es decir, un objeto de valor puede referirse fuertemente a algún otro objeto clave cuyo objeto de valor asociado, a su vez, se refiere fuertemente a la clave del primer objeto de valor. Una forma de lidiar con esto es envolver los valores dentro de WeakReferences antes de insertarlos, como en: m.put (key, new WeakReference (value)), y luego desenvolverlos en cada get.

1 - @Loop tiene un buena respuesta .

2 - Suponiendo que las entradas están envueltas con WeakReferences, la segunda put es necesaria porque esa WeakReference puede recopilarse antes de que la ejecución llegue a la línea:

 Mutex mutex = ref.get();

En este caso:

  • la entrada puede no existir en el map
  • si existe, se puede recopilar antes de la ejecución de Mutex mutex = ref.get ();

Diría que las WeakReference se usan solo porque necesitan referirse a los identificadores de sesión http. No siempre puede estar 100% seguro de recibir una notificación de que una sesión finaliza, lo que provocaría un mapa cada vez mayor.

La primera vez que llamas ponerlo es porque el mapa no contiene tu clave. La segunda vez es porque el mapa contenía la clave pero la referencia ya no existía.

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