Pregunta

He estado leyendo sobre recolección de basura buscando funciones para incluir en mi lenguaje de programación y encontré "indicadores débiles".De aquí:

Los punteros débiles son como punteros, excepto que las referencias de punteros débiles no previenen la recolección de basura, y los punteros débiles deben verificar su validez antes de que se usen.

Los punteros débiles interactúan con el recolector de basura porque la memoria a la que se refieren puede ser válida, pero contiene un objeto diferente al que lo hizo cuando se creó el puntero débil.Por lo tanto, cada vez que un recolector de basura recicla la memoria, debe verificar si hay un puntería débil que se refiera a ella, y marcarlos como inválidos (esto no es necesario implementarse de una manera tan ingenua).

Nunca antes había oído hablar de puntos débiles.Me gustaría admitir muchas funciones en mi idioma, pero en este caso no puedo pensar en un caso en el que esto sea útil.¿Para qué se usaría un puntero débil?

¿Fue útil?

Solución

Un caso de uso típico es el almacenamiento de atributos de los objetos adicionales. Suponga que tiene una clase con un conjunto fijo de miembros, y, desde el exterior, que desea añadir más miembros. Así se crea un objeto de diccionario -> Atributos, donde las claves son referencias débiles. A continuación, el diccionario no impide que las teclas se recolector de basura; extracción del objeto también debe dar lugar a la eliminación de los valores de la WeakKeyDictionary (por ejemplo por medio de una devolución de llamada).

Otros consejos

Uno realmente grande es almacenamiento en caché.Pensemos en cómo funcionaría un caché:

La idea detrás de un caché es almacenar objetos en la memoria hasta que la presión de la memoria sea tan grande que algunos de los objetos deban ser eliminados (o, por supuesto, invalidados explícitamente).Por lo tanto, su objeto de repositorio de caché debe conservar estos objetos de alguna manera.Al retenerlos mediante una referencia débil, cuando el recolector de basura busca cosas para consumir porque la memoria es baja, los elementos a los que se hace referencia solo mediante una referencia débil aparecerán como candidatos para la recolección de basura.Los elementos en el caché que actualmente están siendo utilizados por otro código tendrán referencias físicas aún activas, por lo que esos elementos estarán protegidos de la recolección de basura.

En la mayoría de las situaciones, no utilizará su propio mecanismo de almacenamiento en caché, pero es común utilizar un caché.Supongamos que desea tener una propiedad que haga referencia a un objeto en caché y esa propiedad permanece dentro del alcance durante mucho tiempo.Lo harías preferir para recuperar el objeto del caché, pero si no está disponible, puede obtenerlo del almacenamiento persistente.Tampoco querrás forzar que ese objeto en particular permanezca en la memoria si la presión aumenta demasiado.Entonces puedes usar una referencia débil a ese objeto, lo que te permitirá recuperarlo. si esta disponible pero también permitir que salga del caché.

Si recolector de basura de su lenguaje es incapaz de recoger estructuras de datos circulares, entonces usted puede utilizar referencias débiles a fin de que pueda hacerlo. Normalmente, si tiene dos objetos que tienen referencias a la otra, pero ningún otro objeto fuera tiene una referencia a esos dos, que serían candidatos para la recolección de basura. Sin embargo, un recolector de basura ingenuo no sería recogerlos, ya que contienen referencias a la otra.

Para solucionar este problema, que así sea un objeto tiene una fuerte referencia a la segunda, pero el segundo tiene una débil referencia a la primera. Entonces, cuando la última referencia externa para el primer objeto desaparece, el primer objeto se convierte en un candidato para la recolección de basura, seguido poco después por el segundo, ya que ahora su única referencia es débil.

Otro ejemplo ... no es el almacenamiento en caché, pero similar: Supongamos que una biblioteca de E / S proporciona un objeto que envuelve un descriptor de archivo y permite el acceso al archivo. Cuando se recoge el objeto, el descriptor de archivo se cierra. Se desea ser capaz de enumerar todos los archivos abiertos actualmente. Si utiliza punteros fuertes para esta lista, a continuación, los archivos no se cierran nunca.

Úsalos cuando se quería mantener una lista en caché de objetos, pero no evitar que los objetos entren basura recogida si el propietario "real" del objeto se hace con ella.

Un navegador web podría tener un objeto de la historia que mantiene las referencias a objetos de imagen que el navegador carga en otro lugar y se guarda en la memoria caché de la historia / disco. El navegador web puede caducar una de esas imágenes (usuario borrado la caché, el tiempo de espera transcurrido caché, etc.) pero la página todavía tendría la referencia / puntero. Si la página utiliza una referencia débil / puntero del objeto desaparecería como se esperaba y la memoria sería el recolector de basura.

Una razón importante para tener referencias débiles es hacer frente a la posibilidad de que un objeto puede servir como una tubería para conectar una fuente de información o eventos a uno o más oyentes. Si no hay oyentes, no hay razón para mantener el envío de información a la tubería.

Considere, por ejemplo, una colección enumerable que permite actualizaciones durante la enumeración. La colección puede ser necesario notificar cualquier empadronadores activos que se ha cambiado, por lo que los encuestadores se puede ajustar en consecuencia. Si algunos empadronadores se abandonan por sus creadores, pero la colección se mantiene fuerte referencias a ellos, los enumeradores seguirán existiendo (y notificaciones de actualización de proceso) mientras exista la colección. Si la propia colección existirá para el tiempo de vida de la aplicación, esas enumeradores resultarán efectivamente una pérdida de memoria permanente.

Si la colección contiene referencias débiles a los empadronadores, este problema puede ser resuelto en gran medida. Si se abandona un enumerador, será elegible para la recolección de basura, a pesar de que la colección aún mantiene una referencia débil para él. La próxima vez que se cambia la colección, se puede ver a través de su lista de referencias débiles, enviar actualizaciones a los que aún son válidos, y eliminar de su lista de los que no lo son.

Sería posible lograr muchos de los efectos de las referencias débiles utilizando finalizadores junto con algunos objetos adicionales, y es posible hacer este tipo de implementaciones más eficientes que los que utilizan referencias débiles, pero hay muchas trampas y es difícil de evitar errores . Es mucho más fácil hacer una aproximación correcta usando WeakReference. El enfoque puede no ser óptimamente eficiente, pero no dejará mal.

Punteros débiles mantienen lo que les mantiene convierta en una forma de "soporte vital" para el objeto el puntero apunta a.

Supongamos que tenía una clase de ventana gráfica, y 2 clases de interfaz de usuario, y una de las clases de Buch Widget. Usted quiere que su interfaz de usuario para el control de la vida útil de los widgets que crea, por lo que su interfaz de usuario se mantenga SharedPtrs a todos los widgets que controla. Durante el tiempo que el objeto de interfaz de usuario está vivo, ninguno de los widgets que se refrences basura recogida (gracias a SharedPtr).

Sin embargo, la ventana gráfica es su clase que realmente hace el dibujo, por lo que su interfaz de usuario tiene que pasar la ventana gráfica un puntero a los Reproductores de modo que pueda atraerlos. Por alguna razón, desea cambiar su clase de interfaz de usuario activo para el otro. Vamos a considerar dos escenarios, uno donde la interfaz de usuario pasó los WeakPtrs de ventanilla y uno donde pasó SharedPtrs (señalando a los widgets).

Si se hubiera pasado la ventana gráfica todos los componentes tal y como WeakPointers, tan pronto como se elimina la clase de interfaz de usuario que no habría más SharedPointers a los widgets, por lo que sería basura recogida, las referencias de la vista para los objetos podrían no mantener ellos en "soporte vital", que es exactamente lo que quiere porque no está aún utilizando la interfaz de usuario que más, y mucho menos los widgets que creó.

Ahora, tenga en cuenta que habían pasado la ventana gráfica una SharedPointer, se elimina la interfaz de usuario, y los widgets no son basura recogida! ¿Por qué? debido a que la ventana gráfica, que aún está vivo tiene un array (vector o lista, lo que sea), lleno de SharedPtrs a los widgets. La vista tiene, en efecto, se convirtió en una forma de "soporte vital" para ellos, a pesar de que había eliminado la interfaz de usuario que estaba controlando los widgets para otro objeto de interfaz de usuario.

En general, un lenguaje / sistema / marco se recogen basura nada menos que haya una "fuerte" referencia a él en algún lugar de la memoria. Imagínese si todo tenía una fuerte referencia a todo, nada volvería a conseguir basura recogida! A veces se quiere que el comportamiento a veces no lo hace. Si utiliza un WeakPtr, y no hay Común / StrongPtrs dejaron apunta al objeto (sólo WeakPtrs), a continuación, los objetos serán basura recogida a pesar de las referencias WeakPtr, y los WeakPtrs (deben ser) NULL (o eliminado, o algo).

Una vez más, cuando se utiliza un WeakPtr que está básicamente permite que el objeto que se está dando demasiado para poder acceder a los datos, pero el WeakPtr no va a evitar que la recolección de basura del objeto al que apunta como un SharedPtr sería . Cuando se piensa SharedPtr, piense "soporte vital", WeakPtr, NO "soporte vital". no (en general) se producen recolección de basura hasta que el objeto tiene soporte de vida cero.

referencias débiles pueden usarse, por ejemplo, en escenarios de almacenamiento en caché - se puede acceder a los datos a través de referencias débiles, pero si no accede a los datos durante mucho tiempo o si hay presión de memoria alta, la GC pueden liberarla

La razón de recolección de basura en todo esto es que en un lenguaje como C, donde la gestión de memoria es totalmente bajo el control explícito del programador, cuando la propiedad objeto se pasa alrededor, especialmente entre los hilos o, incluso más duro, entre los procesos que comparten memoria, evitando pérdidas de memoria y punteros colgantes pueden llegar a ser muy duro. Si eso no fuera suficiente, también hay que hacer frente a la necesidad de tener acceso a más objetos de los que caben en la memoria al mismo tiempo-es necesario tener una manera de tener liberar algunos objetos para un tiempo para que otros objetos puede estar en la memoria.

Por lo tanto, algunos idiomas (por ejemplo, Perl, Lisp, Java) proporcionan un mecanismo en el que sólo se puede detener "por medio de" un objeto y el recolector de basura finalmente descubrirán este y liberar la memoria utilizada para el objeto. Esto lo hace correctamente sin que el programador de preocuparse por todas las formas en que pueden hacerlo mal (aunque hay un montón de maneras en que los programadores pueden arruinar esto).

Si conceptualmente multiplica el número de veces que se accede a un objeto por el tiempo que le toma para calcular el valor de un objeto, y posiblemente multiplica de nuevo por el costo de no tener el objeto fácilmente disponibles o por el tamaño de un objeto ya que mantener un objeto grande en torno a la memoria puede prevenir manteniendo varios objetos más pequeños alrededor, se podía clasificar objetos en tres categorías.

Algunos objetos son tan importantes que desea administrar de forma explícita su existencia, no será gestionado por el recolector de basura o que nunca debe ser recogida hasta liberada de forma explícita. Algunos objetos son baratos para calcular, son pequeños, no se accede con frecuencia o tienen características similares que les permitan ser basura recogida en cualquier momento.

La tercera clase, los objetos que son caros para ser recalculado pero podría ser calculados nuevamente, se accede a un tanto con frecuencia (tal vez por una corta ráfaga de tiempo), son de gran tamaño, y así sucesivamente son una tercera clase. Desea mantenerlos en la memoria el mayor tiempo posible, ya que pueden ser reutilizados de nuevo, pero que no quiere que se quede sin memoria necesaria para los objetos críticos. Estos son los candidatos para las referencias débiles.

¿Quieres estos objetos mantenerse tanto tiempo como sea posible si no están en conflicto con los recursos críticos, sino que debe eliminarse si se necesita memoria para un recurso crítico, ya que puede ser recalculado de nuevo cuando sea necesario. Estos son punteros sombrero débiles son para.

Un ejemplo de esto podría ser imágenes. Digamos que tienes una página web de fotos con miles de imágenes para mostrar. Lo que necesita saber cuántos cuadros para diseñar y tal vez tenga que hacer una consulta de base de datos para obtener la lista. La memoria para almacenar una lista de unos pocos miles de artículos es probablemente muy pequeño. Que quiere hacer la consulta una vez y mantenerlo alrededor.

Sólo puede mostrar físicamente tal vez unas pocas docenas de imágenes a la vez, sin embargo, en un panel de una página web. No es necesario ir a buscar a los bits de las imágenes que el usuario no puede mirar. Cuando el usuario se desplaza a la página, usted se reúnen los bits reales de las imágenes visibles. Esas fotos podrían requerir muchos megabytes para mostrarlos. Si el usuario se desplaza hacia atrás y adelante entre unas pocas posiciones de desplazamiento, que le gustaría no tener que vuelva a recuperar esos megabytes una y otra vez. Pero no se puede guardar todas las imágenes en la memoria todo el tiempo. Por lo que utilizar punteros débiles.

Si el usuario sólo se ve en algunas fotos una y otra vez, que pueden permanecer en caché y que no tiene que refetch ellos. Pero si que desplazarse lo suficiente, es necesario liberar espacio en la memoria para que las imágenes visibles se pueden recuperar. Con una referencia débil, se comprueba la referencia justo antes de que lo utilice. Si su todavía válida, que lo utilice. Si no es, se hace el cálculo caro (fetch) para llegar a él.

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