Svag referens
I datorprogrammering är en svag referens en referens som inte skyddar det refererade objektet från insamling av en sophämtare , till skillnad från en stark referens. svagt nåbart Ett objekt som endast refereras av svaga referenser – vilket betyder "varje kedja av referenser som når objektet innehåller minst en svag referens som en länk" – anses vara och kan behandlas som oåtkomligt och kan därför samlas in när som helst. Vissa skräpinsamlade språk har eller stöder olika nivåer av svaga referenser, som C# , Java , Lisp , OCaml , Perl , Python och PHP sedan version 7.4.
Används
Svaga referenser har ett antal vanliga användningsområden. När du använder referensräknande sophämtning kan svaga referenser bryta referenscykler genom att använda en svag referens för en länk i cykeln. När man har en associativ array (mappning, hashkarta) vars nycklar är (referenser till) objekt, till exempel för att hålla hjälpdata om objekt, undviker man att använda svaga referenser för nycklarna att hålla objekten vid liv bara på grund av att de används som nycklar. När man har ett objekt där andra objekt är registrerade, t.ex. i observatörsmönstret ( särskilt vid händelsehantering ), om en stark referens hålls, måste objekten uttryckligen avregistreras, annars uppstår en minnesläcka ( problemet med förfallen lyssnare ), medan en svag referens tar bort behovet av att avregistrera sig. När cachad data lagras som kan återskapas vid behov, gör svaga referenser att cachen kan återvinnas, vilket effektivt producerar kasseringsbart minne. Det sista fallet (en cache) skiljer sig från andra, då det är att föredra att föremålen endast sopsamlas vid behov, och det finns därför behov av finare distinktioner inom svaga referenser, här en starkare form av en svag referens. I många fall behöver svaga referenser inte användas direkt, utan bara använda en svag array eller annan behållare vars nycklar eller värden är svaga referenser.
Skräp samling
Sophämtning används för att städa upp oanvända föremål och på så sätt minska risken för minnesläckor och datakorruption. Det finns två huvudtyper av sophämtning: spårning och referensräkning . Referensräkningsscheman registrerar antalet referenser till ett givet objekt och samlar in objektet när referensräkningen blir noll. Referensräkning kan inte samla in cykliska (eller cirkulära) referenser eftersom endast ett objekt kan samlas in åt gången. Grupper av ömsesidigt refererande objekt som inte direkt refereras av andra objekt och som inte går att nå kan därmed bli permanent bosatta; om ett program kontinuerligt genererar sådana oåtkomliga grupper av oåtkomliga objekt kommer detta att få effekten av en minnesläcka . Svaga referenser (referenser som inte räknas i referensräkning) kan användas för att lösa problemet med cirkulära referenser om referenscyklerna undviks genom att använda svaga referenser för några av referenserna inom gruppen.
Ett mycket vanligt fall av sådana starka kontra svaga referensskillnader är i trädstrukturer, såsom Document Object Model (DOM), där förälder-till-barn-referenser är starka, men barn-till-förälder-referenser är svaga. Till exempel rekommenderar Apples Cocoa -ramverk detta tillvägagångssätt. Faktum är att även när objektgrafen inte är ett träd, kan en trädstruktur ofta påtvingas av begreppet objektägande, där ägandeförhållanden är starka och bildar ett träd, och icke-ägandeförhållanden är svaga och inte behövs för att bilda trädet – detta tillvägagångssätt är vanligt i C++ (pre-C++11), med råpekare som svaga referenser. Detta tillvägagångssätt har dock nackdelen att inte tillåta möjligheten att upptäcka när en överordnad gren har tagits bort och tagits bort. Sedan C++11- standarden har en lösning lagts till genom att använda shared_ptr och weak_ptr , ärvt från Boost -biblioteket.
Svaga referenser används också för att minimera antalet onödiga objekt i minnet genom att tillåta programmet att indikera vilka objekt som är av mindre betydelse genom att endast svagt referera till dem. [ citat behövs ]
Variationer
Vissa språk har flera nivåer av svag referensstyrka. Till exempel Java , i ordning efter minskande styrka, mjuka , svaga och fantomreferenser , definierade i paketet java.lang.ref . Varje referenstyp har ett tillhörande begrepp om nåbarhet. Sophämtaren (GC) använder ett objekts typ av nåbarhet för att bestämma när objektet ska frigöras. Det är säkert för GC att frigöra ett objekt som är lätt att nå, men GC kan besluta att inte göra det om den tror att JVM kan spara minnet (t.ex. har JVM mycket oanvänt högutrymme). GC:n kommer att frigöra ett svagt nåbart objekt så snart GC:n märker objektet. Till skillnad från de andra referenstyperna kan en fantomreferens inte följas. Å andra sidan tillhandahåller fantomreferenser en mekanism för att meddela programmet när ett objekt har frigjorts (meddelande implementeras med hjälp av ReferenceQueues).
I C# särskiljs svaga referenser av om de spårar objektets återuppståndelse eller inte. Denna distinktion förekommer inte för starka referenser, eftersom objekt inte slutbehandlas om de har några starka referenser till dem. Som standard, i C# spårar inte svag referens återuppståndelse, vilket innebär att en svag referens inte uppdateras om ett objekt återuppstår; dessa kallas korta svaga referenser och svaga referenser som spårar uppståndelse kallas långa svaga referenser .
Vissa språk som inte samlas in för skräp, som C++ , tillhandahåller svag/stark referensfunktion som en del av att stödja sopsamlingsbibliotek. Boost C++-biblioteket ger starka och svaga referenser. Det är ett misstag att använda vanliga C++-pekare som de svaga motsvarigheterna till smarta pekare eftersom sådan användning tar bort möjligheten att upptäcka när den starka referensräkningen har gått till 0 och objektet har tagits bort. Ännu värre, det tillåter inte detektering av om en annan stark referens redan spårar en given vanlig pekare. Detta introducerar möjligheten att ha två (eller flera) smarta pekare som spårar samma vanliga pekare (vilket orsakar korruption så snart en av dessa smarta pekares referensräkning når 0 och objektet raderas).
Exempel
Svaga referenser kan vara användbara när du håller en lista över de aktuella variablerna som refereras till i applikationen. Denna lista måste ha svaga länkar till objekten. Annars, när objekt läggs till i listan, kommer de att refereras av den och kommer att finnas kvar under programmets varaktighet.
Java
Java 1.2 introducerade 1998 två typer av svaga referenser, en känd som en "mjuk referens" (avsedd att användas för att underhålla GC-hanterade cacher i minnet, men som inte fungerar särskilt bra i praktiken på vissa plattformar med dynamisk heap som Android) och den andra helt enkelt som en "svag referens". Den lade också till en relaterad experimentell mekanism kallad "fantomreferenser" som ett alternativ till den farliga och ineffektiva finalize()-mekanismen.
Om en svag referens skapas, och sedan någon annanstans i koden get()
används för att hämta det faktiska objektet, är den svaga referensen inte tillräckligt stark för att förhindra sophämtning, så det kan vara (om det inte finns några starka referenser till objekt) att get()
plötsligt börjar returnera null.
importera java.lang.ref.WeakReference ; public class ReferenceTest { public static void main ( String [] args ) throws InterruptedException { WeakReference r = new WeakReference ( "Jag är här" ); StrongReference sr = new StrongReference ( "Jag är här" ) ; System . ut . println ( "Innan gc: r=" + r . get () + ", static=" + sr . get ()); System . gc (); Tråd . sömn ( 100 ); // Endast r.get() blir null. System . ut . println ( "Efter gc: r=" + r . get () + ", static=" + sr . get ()); } }
En annan användning av svaga referenser är att skriva en cache . Med hjälp av till exempel en svag hashkarta kan man lagra de olika refererade objekten i cachen via en svag referens. När sopsamlaren körs - när till exempel applikationens minnesanvändning blir tillräckligt hög - tas de cachade objekt som inte längre direkt refereras av andra objekt bort från cachen.
Småprat
| a s1 s2 | s1 := 'hej' kopia . "det är en stark referens" s2 := 'världs' kopia . "det är en stark referens" a := WeakArray med: s1 med: s2 . a printOn: Transcript . ObjectMemory collectGarbage . a printOn: Transcript . "båda elementen kvar" s1 := noll . "stark referens försvinner" ObjectMemory collectGarbage . a printOn: Transcript . "första elementet borta" s2 := noll . "stark referens försvinner" ObjectMemory collectGarbage . a printOn: Transcript . "andra element borta"
Lua
weak_table = setmetatable ({}, { __mode = "v" }) weak_table . item = {} print ( weak_table . item ) collect garbage ( ) print ( weak_table . item )
Objective-C 2.0
I Objective-C 2.0 kommer inte bara sophämtning utan även automatisk referensräkning att påverkas av svaga referenser. Alla variabler och egenskaper i följande exempel är svaga.
@interface WeakRef : NSObject { __weak NSString * str1 ; __unsafe_unretained NSString * str2 ; } @property ( icke-atomisk , svag ) NSString * str3 ; @property ( ickeatomic , unsafe_unretained ) NSString * str4 ; @slutet
Skillnaden mellan svag
( __weak
) och unsafe_unretained
( __unsafe_unretained
) är att när objektet som variabeln pekade på avallokeras, oavsett om värdet på variabeln kommer att ändras eller inte. svaga
kommer att uppdateras till noll
och den unsafe_unretained
kommer att lämnas oförändrad, som en dinglande pekare . De svaga
referenserna läggs till i Objective-C sedan Mac OS X 10.7 "Lion" och iOS 5 , tillsammans med Xcode 4.1 (4.2 för iOS), och endast när man använder ARC. Äldre versioner av Mac OS X, iOS och GNUstep stöder endast unsafe_unretained
referenser som svaga.
Vala
class Node { public weak Node prev ; // en svag referens används för att undvika cirkulära referenser mellan noder i en dubbellänkad lista public Node next ; }
Pytonorm
>>> importera svagref >>> importera gc >>> klass Ägg : ... def spam ( self ): ... print ( "Jag lever!" ) ... >>> obj = Ägg () > >> weak_obj = svagref . ref ( obj ) >>> weak_obj ( ) . spam () Jag lever! >>> obj = "Något annat" >>> gc . samla () 35 >>> weak_obj () . spam () Traceback (senaste anropet senast): Fil "<stdin>" , rad 1 , i <modul> AttributeError : 'NoneType'-objektet har inget attribut 'spam'
Se även
- Goldshtein, Sasha; Zurbalev, Dima; Flatow, Ido (2012). Pro .NET-prestanda: Optimera dina C#-applikationer . Apress. ISBN 978-1-4302-4458-5 .
externa länkar
C++
-
C++11 Standardbibliotek :
std::weak_ptr
referens -
Boost 1.59 (C++-bibliotek) :
boost::weak_ptr-
referens
Java
- Java-utvecklarartikel: "Referensobjekt och skräpinsamling"
- Nicholas, Ethan (4 maj 2006). "Förstå svaga referenser" . java.net . Arkiverad från originalet 2011-03-03 . Hämtad 1 oktober 2010 .
- RCache - Java Library för svag/mjuk referensbaserad cache
- Java teori och praktik: Plugga minnesläckor med svaga referenser
PHP
Pytonorm
- weakref — Svaga referenser — Python 3-dokumentation
- Fred L. Drake, Jr., PEP 205: Weak References , Python Enhancement Proposal, januari 2001.