stringtranslate.com

Referencia débil

En programación de computadoras , una referencia débil es una referencia que no protege el objeto al que se hace referencia de la recolección por parte de un recolector de basura , a diferencia de una referencia fuerte. Un objeto al que se hace referencia únicamente mediante referencias débiles (lo que significa "cada cadena de referencias que llega al objeto incluye al menos una referencia débil como vínculo") se considera débilmente alcanzable y puede tratarse como inalcanzable y, por lo tanto, puede recopilarse en cualquier momento. Algunos lenguajes de recolección de basura presentan o admiten varios niveles de referencias débiles, como C# , Lua , Java , Lisp , OCaml , Perl , Python [1] y PHP desde la versión 7.4. [2]

Usos

Las referencias débiles tienen varios usos comunes. Cuando se utiliza la recolección de basura con recuento de referencias , las referencias débiles pueden romper los ciclos de referencia al utilizar una referencia débil para un enlace en el ciclo. Cuando uno tiene una matriz asociativa (mapeo, mapa hash) cuyas claves son (referencias a) objetos, por ejemplo para contener datos auxiliares sobre objetos, el uso de referencias débiles para las claves evita mantener vivos los objetos solo por su uso como claves. Cuando uno tiene un objeto donde otros objetos están registrados, como en el patrón de observador (particularmente en el manejo de eventos ), si se mantiene una referencia fuerte, los objetos deben cancelarse explícitamente; de ​​lo contrario, se produce una pérdida de memoria (el problema del oyente caducado ), mientras que una referencia débil elimina la necesidad de cancelar el registro. Cuando se mantienen datos almacenados en caché que se pueden recrear si es necesario, las referencias débiles permiten recuperar el caché, lo que produce efectivamente memoria descartable. Este último caso (un caché) es distinto de otros, ya que es preferible que los objetos solo se recolecten como basura si es necesario y, por lo tanto, existe la necesidad de distinciones más finas dentro de las referencias débiles, aquí una forma más fuerte de referencia débil. En muchos casos, no es necesario utilizar referencias débiles directamente, sino simplemente utilizar una matriz débil u otro contenedor cuyas claves o valores sean referencias débiles.

Recolección de basura

La recolección de basura se utiliza para limpiar objetos no utilizados y así reducir la posibilidad de pérdidas de memoria y corrupción de datos. Hay dos tipos principales de recolección de basura: rastreo y recuento de referencias . Los esquemas de recuento de referencias registran el número de referencias a un objeto determinado y recopilan el objeto cuando el recuento de referencias llega a cero. El recuento de referencias no puede recopilar referencias cíclicas (o circulares) porque sólo se puede recopilar un objeto a la vez. Los grupos de objetos que hacen referencias mutuas a los que otros objetos no hacen referencia directamente y son inalcanzables pueden, por tanto, convertirse en residentes permanentes; Si una aplicación genera continuamente grupos inalcanzables de objetos inalcanzables, esto tendrá el efecto de una pérdida de memoria . Las referencias débiles (referencias que no se cuentan en el recuento de referencias) se pueden utilizar para resolver el problema de las referencias circulares si se evitan los ciclos de referencia utilizando referencias débiles para algunas de las referencias dentro del grupo.

Un caso muy común de distinciones de referencias fuertes versus débiles es en estructuras de árbol, como el Modelo de objetos de documento (DOM), donde las referencias de padre a hijo son fuertes, pero las referencias de hijo a padre son débiles. Por ejemplo, el marco Cocoa de Apple recomienda este enfoque. [3] De hecho, incluso cuando el gráfico de objetos no es un árbol, a menudo se puede imponer una estructura de árbol mediante la noción de propiedad del objeto, donde las relaciones de propiedad son fuertes y forman un árbol, y las relaciones de no propiedad son débiles y no son necesarias para formar el árbol: este enfoque es común en C++ (anterior a C++11), y utiliza punteros sin formato como referencias débiles. Este enfoque, sin embargo, tiene la desventaja de no permitir la capacidad de detectar cuándo se ha eliminado y eliminado una rama principal. Desde el estándar C++ 11 , se agregó una solución usando shared_ptr y débil_ptr , heredados de la biblioteca Boost .

Las referencias débiles también se utilizan para minimizar la cantidad de objetos innecesarios en la memoria al permitir que el programa indique qué objetos son de menor importancia haciendo referencia a ellos solo débilmente. [ cita necesaria ]

Variaciones

Algunos idiomas tienen múltiples niveles de fuerza de referencia débil. Por ejemplo, Java tiene, en orden decreciente de fuerza, referencias suaves , débiles y fantasmas , definidas en el paquete java.lang.ref . [4] Cada tipo de referencia tiene una noción asociada de accesibilidad. El recolector de basura (GC) utiliza el tipo de accesibilidad de un objeto para determinar cuándo liberarlo. Es seguro para el GC liberar un objeto al que se puede acceder suavemente, pero el GC puede decidir no hacerlo si cree que la JVM puede ahorrar memoria (por ejemplo, la JVM tiene mucho espacio de almacenamiento dinámico sin utilizar). El GC liberará un objeto de difícil acceso tan pronto como lo detecte. A diferencia de otros tipos de referencia, no se puede seguir una referencia fantasma. Por otro lado, las referencias fantasma proporcionan un mecanismo para notificar al programa cuando se libera un objeto (la notificación se implementa mediante ReferenceQueues).

En C#, las referencias débiles se distinguen según si rastrean la resurrección del objeto o no. Esta distinción no ocurre con referencias fuertes, ya que los objetos no están finalizados si tienen referencias fuertes a ellos. De forma predeterminada, en C#, las referencias débiles no rastrean la resurrección, lo que significa que una referencia débil no se actualiza si un objeto resucita; éstas se llaman referencias débiles cortas , y las referencias débiles que siguen la resurrección se llaman referencias débiles largas . [5]

Algunos lenguajes que no recolectan basura, como C++ , proporcionan una funcionalidad de referencia débil/fuerte como parte del soporte de las bibliotecas de recolección de basura. La biblioteca Boost C++ proporciona referencias fuertes y débiles. Es un error utilizar punteros C++ normales como contrapartes débiles de los punteros inteligentes porque dicho uso elimina la capacidad de detectar cuándo el recuento de referencias fuertes ha llegado a 0 y el objeto se ha eliminado. Peor aún, no permite detectar si otra referencia fuerte ya está siguiendo un puntero simple determinado. Esto introduce la posibilidad de tener dos (o más) punteros inteligentes rastreando el mismo puntero simple (lo que causa corrupción tan pronto como el recuento de referencias de uno de estos punteros inteligentes llega a 0 y el objeto se elimina).

Ejemplos

Las referencias débiles pueden resultar útiles a la hora de mantener una lista de las variables actuales a las que se hace referencia en la aplicación. Esta lista debe tener vínculos débiles con los objetos. De lo contrario, una vez que se agregan objetos a la lista, ésta hará referencia a ellos y persistirán mientras dure el programa.

Java

Java 1.2 en 1998 introdujo [6] dos tipos de referencias débiles, una conocida como "referencia suave" (destinada a mantener cachés en memoria administradas por GC, pero que no funciona muy bien en la práctica en algunas plataformas con montón dinámico como Android [7] ) y el otro simplemente como una "referencia débil". También agregó un mecanismo experimental relacionado denominado "referencias fantasma" como una alternativa al peligroso e ineficiente mecanismo finalize(). [8]

Si se crea una referencia débil y luego se utiliza otra parte del código get()para obtener el objeto real, la referencia débil no es lo suficientemente fuerte como para evitar la recolección de basura, por lo que puede ser (si no hay referencias fuertes al objeto) que get()de repente comienza a devolver nulo. [9]

importar java.lang.ref.WeakReference ; prueba de referencia de clase pública { public static void main ( String [] args ) lanza InterruptedException { WeakReference r = new WeakReference ( "Estoy aquí" ); StrongReference sr = nueva StrongReference ( "Estoy aquí" ); Sistema . afuera . println ( "Antes de gc: r=" + r . get () + ", static=" + sr . get ()); Sistema . gc (); Hilo . dormir ( 100 );                               // Sólo r.get() se vuelve nulo. Sistema . afuera . println ( "Después de gc: r=" + r . get () + ", static=" + sr . get ()); } }        

Otro uso de las referencias débiles es escribir un caché . Usando, por ejemplo, un mapa hash débil , se pueden almacenar en el caché los distintos objetos referidos a través de una referencia débil. Cuando se ejecuta el recolector de basura (cuando, por ejemplo, el uso de memoria de la aplicación aumenta lo suficiente), los objetos almacenados en caché a los que otros objetos ya no hacen referencia directamente se eliminan del caché.

Charla

| un s1 s2 |s1  : =  'hola'  copia .  "Esa es una referencia sólida" s2  : =  copia 'mundo'  . "Esa es una referencia fuerte" a := WeakArray con: s1 con: s2 . a printOn: Transcripción . ObjetoMemoria recoger basura . a printOn: Transcripción . "ambos elementos siguen ahí"            s1  : =  nulo .  "La referencia fuerte desaparece"  ObjectMemory  CollectGarbage . a  printOn:  Transcripción .  "el primer elemento desapareció"s2  : =  nulo .  "La referencia fuerte desaparece"  ObjectMemory  CollectGarbage . a  printOn:  Transcripción .  "el segundo elemento desapareció"

lua

tabla_débil  =  setmetatable ({},  { __mode = "v" }) tabla_débil . elemento  =  {} imprimir ( tabla_débil . elemento ) recoger basura () imprimir ( tabla_débil . elemento )

Objetivo-C 2.0

En Objective-C 2.0, no solo la recolección de basura, sino también el recuento automático de referencias se verán afectados por referencias débiles. Todas las variables y propiedades del siguiente ejemplo son débiles.

@interface  WeakRef  : NSObject { __weak NSString * str1 ; __unsafe_unretained NSString * str2 ; }      @property ( no atómico , débil ) NSString * str3 ; @property ( nonatomic , unsafe_unretained ) NSString * str4 ;        @fin

La diferencia entre weak( __weak) y unsafe_unretained( __unsafe_unretained) es que cuando el objeto al que apuntaba la variable se desasigna, se cambiará o no el valor de la variable. weakunos se actualizarán nily el unsafe_unretainedotro se dejará sin cambios, como un puntero colgante . Las weakreferencias se agregan a Objective-C desde Mac OS X 10.7 "Lion" e iOS 5 , junto con Xcode 4.1 (4.2 para iOS), y solo cuando se usa ARC. Las versiones anteriores de Mac OS X, iOS y GNUstep solo admiten unsafe_unretainedreferencias débiles.

vala

clase Nodo { público débil Nodo anterior ; // se utiliza una referencia débil para evitar referencias circulares entre nodos de una lista doblemente enlazada public Node next ; }          

Pitón

>>> importar  débilesref >>> importar  gc >>> clase  Huevo : ...  def  spam ( self ): ...  print ( "¡Estoy vivo!" ) ... >>> obj  =  Huevo () > >> obj_débil  =  refdébil . ref ( obj ) >>> objeto_débil () . spam () ¡Estoy vivo! >>> obj  =  "Algo más" >>> gc . recopilar () 35 >>> objeto_débil () . spam () Rastreo (última llamada más reciente): Archivo "<stdin>" , línea 1 , en <módulo> AttributeError : el objeto 'NoneType' no tiene el atributo 'spam'

Ver también

Referencias

  1. ^ 8.8. débilref: referencias débiles, la biblioteca estándar de Python
  2. ^ "PHP: Referencia débil - Manual".
  3. ^ "Gestión práctica de la memoria". desarrollador.apple.com .
  4. ^ Nicholas, Ethan (4 de mayo de 2006). "Comprensión de las referencias débiles". java.net . Archivado desde el original el 3 de marzo de 2011 . Consultado el 1 de octubre de 2010 .
  5. ^ Goldshtein, Zurbalev y Flatow 2012, pág. 131.
  6. ^ "Referencia débil (plataforma Java SE 7)". docs.oracle.com .
  7. ^ "SoftReference: desarrolladores de Android". desarrollador.android.com .
  8. ^ "PhantomReference (Plataforma Java SE 7)". docs.oracle.com .
  9. ^ https://web.archive.org/web/20110303225354/http://weblogs.java.net/blog/2006/05/04/understanding-weak-references Ejemplos de Java

enlaces externos

C++

Java

PHP

Pitón