Слабая ссылка

редактировать

В компьютерном программировании слабая ссылка - это ссылка, которая не защищает указанные объект из коллекции сборщиком мусора , в отличие от строгой ссылки. Объект, на который ссылаются только слабые ссылки - то есть «каждая цепочка ссылок, которая достигает объекта, включает по крайней мере одну слабую ссылку в качестве ссылки» - считается слабо достижимым и может рассматриваться как недостижимый и поэтому могут быть собраны в любое время. Некоторые языки со сборкой мусора имеют или поддерживают различные уровни слабых ссылок, например C#, Java, Lisp, OCaml, Perl, Python и PHP, начиная с версии 7.4.

Содержание
  • 1 Используется
  • 2 Сборка мусора
  • 3 Варианты
  • 4 Примеры
    • 4.1 Java
    • 4.2 Smalltalk
    • 4.3 Lua
    • 4.4 Objective-C 2.0
    • 4.5 Vala
    • 4.6 Python
  • 5 См. Также
  • 6 Ссылки
  • 7 Внешние ссылки
    • 7.1 C ++
    • 7.2 Java
    • 7.3 PHP
    • 7.4 Python
Использует

У слабых ссылок есть несколько распространенных вариантов использования. При использовании подсчета ссылок сборка мусора слабые ссылки могут нарушить ссылочные циклы, используя слабую ссылку для ссылки в цикле. Когда у вас есть ассоциативный массив (отображение, хэш-карта), ключи которого (ссылки на) объекты, например, для хранения вспомогательных данных об объектах, использование слабых ссылок для ключей позволяет избежать сохранения объектов в живых только из-за их использование в качестве ключа. Если есть объект, в котором зарегистрированы другие объекты, например, в шаблоне наблюдателя (особенно в обработке событий ), если сохраняется строгая ссылка, объекты должны быть явно разрегистрированы, иначе происходит утечка памяти (проблема пропущенного слушателя ), а слабая ссылка устраняет необходимость отмены регистрации. При хранении кэшированных данных, которые можно воссоздать при необходимости, слабые ссылки позволяют восстановить кэш, эффективно создавая сбрасываемую память. Этот последний случай (кеш) отличается от других, так как предпочтительно, чтобы объекты собирались мусором только в случае необходимости, и, таким образом, существует потребность в более тонких различиях внутри слабых ссылок, здесь более сильная форма слабой ссылки. Во многих случаях нет необходимости напрямую использовать слабые ссылки, вместо этого просто используйте слабый массив или другой контейнер, ключи или значения которого являются слабыми ссылками.

Сборка мусора

Сборка мусора используется для очистки неиспользуемых объектов и снижения вероятности утечек памяти и повреждения данных. Существует два основных типа сборки мусора: трассировка и подсчет ссылок. Схемы подсчета ссылок записывают количество ссылок на данный объект и собирают объект, когда счетчик ссылок становится равным нулю. Подсчет ссылок не может собирать циклические (или циклические) ссылки, потому что одновременно может собираться только один объект. Группы взаимно ссылающихся объектов, на которые не ссылаются напрямую другие объекты и которые недоступны, могут, таким образом, стать постоянно резидентными; если приложение постоянно генерирует такие недостижимые группы недостижимых объектов, это будет иметь эффект утечки памяти. Слабые ссылки (ссылки, которые не учитываются при подсчете ссылок) могут использоваться для решения проблемы циклических ссылок, если циклы ссылок избегаются путем использования слабых ссылок для некоторых ссылок в группе.

Очень распространенный случай таких сильных и слабых различий ссылок - в древовидных структурах, таких как Document Object Model (DOM), где ссылки между родительскими и дочерними элементами сильны, но ссылки между дочерними и родительскими объектами слабые. Например, структура Apple Cocoa рекомендует этот подход. В самом деле, даже когда граф объекта не является деревом, древовидная структура часто может быть навязана понятием владения объектом, где отношения собственности сильны и образуют дерево, а отношения, не связанные с владением, являются слабыми и не нужны для формирования дерева - этот подход распространен в C ++ (до C ++ 11), где необработанные указатели используются в качестве слабых ссылок. Однако у этого подхода есть обратная сторона: он не позволяет определять, когда родительская ветвь была удалена и удалена. Начиная со стандарта C ++ 11, решение было добавлено с использованием shared_ptr и weak_ptr, унаследованных от платформы Boost.

Слабые ссылки также используются для минимизации количества ненужных объектов в памяти, позволяя программе указывать, какие объекты менее важны, лишь слабо ссылаясь на них.

Варианты

Некоторые языки имеют несколько уровней слабой ссылочной силы. Например, Java имеет в порядке убывания силы мягкие, слабые и фантомные ссылки, определенные в пакете java.lang.ref. С каждым ссылочным типом связано понятие достижимости. Сборщик мусора (GC) использует тип достижимости объекта, чтобы определить, когда освободить объект. Для GC безопасно освободить объект, который легко доступен, но GC может решить не делать этого, если считает, что JVM может сэкономить память (например, JVM имеет много неиспользуемого пространства кучи). Сборщик мусора освободит слабодоступный объект, как только сборщик мусора заметит этот объект. В отличие от других типов ссылок, за фантомной ссылкой нельзя следовать. С другой стороны, фантомные ссылки предоставляют механизм для уведомления программы, когда объект был освобожден (уведомление реализуется с помощью ReferenceQueues).

В C # слабые ссылки различаются по тому, отслеживают ли они воскрешение объекта или нет. Это различие не происходит для строгих ссылок, поскольку объекты не являются финализированными, если на них есть какие-либо строгие ссылки. По умолчанию в C # слабая ссылка не отслеживает воскрешение, то есть слабая ссылка не обновляется при воскрешении объекта; они называются короткими слабыми ссылками, а слабые ссылки, которые отслеживают воскрешение, называются длинными слабыми ссылками .

Некоторые языки без сбора мусора, такие как C ++, предоставляют слабые / сильная справочная функциональность как часть поддержки библиотек сборки мусора. Библиотека Boost C ++ предоставляет сильные и слабые ссылки. Ошибочно использовать обычные указатели C ++ в качестве слабых аналогов интеллектуальных указателей, потому что такое использование лишает возможности определять, когда счетчик сильных ссылок перешел в 0 и объект был удален. Что еще хуже, он не позволяет определить, отслеживает ли уже другая сильная ссылка данный простой указатель. Это вводит возможность наличия двух (или более) интеллектуальных указателей, отслеживающих один и тот же простой указатель (что вызывает повреждение, как только счетчик ссылок одного из этих интеллектуальных указателей достигает 0 и объект удаляется).

Примеры

Слабые ссылки могут быть полезны при ведении списка текущих переменных, на которые ссылается приложение. В этом списке должны быть слабые ссылки на объекты. В противном случае, как только объекты будут добавлены в список, они будут ссылаться на них и будут сохраняться на протяжении всей программы.

Java

Java 1.2 в 1998 г. представила два типа слабых ссылок, один из которых известен как «мягкая ссылка» (предназначенный для использования для поддержки кешей в памяти, управляемых сборщиком мусора, но не не очень хорошо работает на практике на некоторых платформах с динамической кучей (например, Android), а на других просто как «слабая ссылка». Он также добавил связанный экспериментальный механизм, названный «фантомные ссылки», в качестве альтернативы опасному и неэффективному механизму finalize ().

Если создается слабая ссылка, а затем в другом месте кода get ()используется для получения фактического объекта, слабая ссылка недостаточно сильна, чтобы предотвратить сборку мусора, поэтому может быть (если нет сильных ссылок на объект), что get ()внезапно начинает возвращать null.

import java.lang.ref.WeakReference; открытый класс ReferenceTest {public static void main (String args) выбрасывает InterruptedException {WeakReference r = new WeakReference ("Я здесь"); StrongReference sr = new StrongReference («Я здесь»); System.out.println ("До gc: r =" + r.get () + ", static =" + sr.get ()); System.gc (); Thread.sleep (100); // Только r.get () становится нулевым. System.out.println ("После gc: r =" + r.get () + ", static =" + sr.get ()); }}

Еще одно применение слабых ссылок - это запись кеша. Используя, например, слабую хэш-карту , можно хранить в кэше различные упомянутые объекты через слабую ссылку. При запуске сборщика мусора - когда, например, использование памяти приложением становится достаточно высоким - те кэшированные объекты, на которые больше не ссылаются напрямую другие объекты, удаляются из кеша.

Smalltalk

| a s1 s2 | s1: = 'привет' копия. "это сильная ссылка" s2: = 'world' copy. «это сильная ссылка» a: = WeakArray с: s1 с: s2. printOn: стенограмма. ObjectMemory collectGarbage. printOn: стенограмма. "оба элемента все еще там" s1: = nil. «сильная ссылка уходит» ObjectMemory collectGarbage. printOn: стенограмма. "первый элемент ушел" s2: = nil. «сильная ссылка уходит» ObjectMemory collectGarbage. printOn: стенограмма. "второй элемент пропал"

Lua

weak_table = setmetatable ({}, {__mode = "v"}) weak_table.item = {} print (weak_table.item) collectgarbage () print (weak_table.item)

Objective-C 2.0

В Objective-C 2.0 слабые ссылки будут влиять не только на сборку мусора, но и на автоматический подсчет ссылок. Все переменные и свойства в следующем примере являются слабыми.

@interface WeakRef: NSObject {__weak NSString * str1; __unsafe_unreolated NSString * str2; } @property (неатомный, слабый) NSString * str3; @property (неатомный, небезопасный_безопасный) NSString * str4; @end

Разница между weak(__weak) и unsafe_unrehibited(__unsafe_unrehibited) заключается в том, что когда объект, на который указывает переменная освобождается независимо от того, будет ли изменено значение переменной или нет. слабыебудут обновлены до nil, а unsafe_unrehibitedостанется без изменений, как висячий указатель. Ссылки weakдобавлены в Objective-C начиная с Mac OS X 10.7 "Lion" и iOS 5 вместе с Xcode 4.1 ( 4.2 для iOS), и только при использовании ARC. Более старые версии Mac OS X, iOS и GNUstep поддерживают только ссылки unsafe_unrehibitedкак слабые.

Vala
class Node {public weak Node prev; // используется слабая ссылка, чтобы избежать циклических ссылок между узлами двусвязного списка public Node next; }

Python

>>>import weakref>>>import gc>>>class Egg:... def spam (self):... print ("Я жив!")...>>>obj = Egg ()>>>weak_obj = weakref.ref (obj)>>>weak_obj (). spam () Я жив!>>>obj = "Something else">>>gc.collect () 35>>>weak_obj (). spam () Traceback (последний вызов последним): файл "", строка 1, в AttributeError: объект 'NoneType' не имеет атрибута 'spam'
См. Также
Ссылки
Внешние ссылки

C ++

Java

PHP

Python

Последняя правка сделана 2021-06-20 10:19:54
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте