본문 바로가기
C#

[C#] WeakReference

by DANEW 2023. 10. 14.

WeakReference 클래스

 

WeakReference 클래스 (System)

가비지 수집에 의한 개체 회수를 허용하면서 개체를 참조하는 약한 참조를 나타냅니다.

learn.microsoft.com

namespace System
{
    public class WeakReference : ISerializable
    {
        public WeakReference(object target);
        public WeakReference(object target, bool trackResurrection);
        protected WeakReference(SerializationInfo info, StreamingContext context);
        ~WeakReference();
 
        public virtual bool IsAlive { get; }
        public virtual bool TrackResurrection { get; }
        public virtual object Target { get; set; }
 
        public virtual void GetObjectData(SerializationInfo info, StreamingContext context);
    }
}

- GC가 객체에 대한 참조를 볼 수 없게 만드는 참조 - 약한 참조(Weak Reference)

namespace Practice
{
    class Program
    {
        public static void Main(string[] arg)
        {
            // 약한 참조는 GC 이후 사라진다.
            var weak = new WeakReference(new StringBuilder("약한 참조"));
            Console.WriteLine(weak.Target); // 약한 참조
            GC.Collect();
            Console.WriteLine(weak.Target); // (출력 없음)
 
 
            // 약한 참조를 강한 뿌리 참조로 묶어놓기
            weak = new WeakReference(new StringBuilder("약한 참조"));
            var strBuilder = (StringBuilder)weak.Target;
            Console.WriteLine(weak.Target); // 약한 참조
            GC.Collect();
            Console.WriteLine(weak.Target); // 약한 참조
        }
    }
}
반응형
class Widget
{
    // List를 통해 약한 참조를 관리
    // - 시간이 흐르면서 정적 목록이 계속 길어짐
    // - 대상이 NULL인 약한 참조들이 누적됨
 
    // 모든 원소가 약한 참조이므로
    // 다른 참조가 없다면 GC 실행시에 모두 사라짐
    static List<WeakReference> allWidgets = new List<WeakReference>();
 
    public readonly string name;
 
    public Widget(string name)
    {
        this.name = name;
        allWidgets.Add(new WeakReference(this));
    }
 
    public static void PrintAllWidgets()
    {
        foreach (var item in allWidgets)
        {
            Widget w = (Widget)item.Target;
            if (w != null)
            {
                Console.WriteLine(w.name);
            }
        }
    }
}

약한 참조와 캐싱
- 약한 참조를 커다란 객체 그래프를 캐싱하는데 사용 할 수 있음
- 메모리를 많이 사용하는 자료를 잠시 동안 캐싱 할 때 메모리를 추가로 과도하게 소비할 필요가 없음

// _weakCache는 클래스의 한 필드
_weakCache = new WeakReference( /* ... */ );
 
// ...
 
var cache = _weakCache.Target;
 
if(cache == null)
{
    // 캐시를 재생성해서 _weakCache에 배정
}


- GC가 언제 발생할지 모르기 때문에 위 방식은 실무에 부적합
- 강한 참조를 유지하는 것으로 시작해 시간이 지남에 따라 약한 참조로 바꾸는 등의 방식을 구현해야 함

반응형