이전 기사에서 참조 및 값별 참조에 대해 배웠습니다. 우리는 PHP에는 순수한 참조(포인터)가 없다는 것을 알고 있습니다. 객체이든 참조 기호 &가 할당된 변수이든 기호 테이블에 대한 참조입니다. 오늘은 또 다른 참조 형태인 약한 참조에 대해 알아보겠습니다.
약한 참조란 무엇입니까?
약한 참조는 프로그래머가 객체가 파괴되는 것을 방지하지 않고 객체에 대한 참조를 유지할 수 있도록 해줍니다. 캐시와 같은 구조를 구현하는 데 유용합니다.
좀 더 공식적인 설명입니다. 이 설명에서 약한 참조도 참조의 한 형태임을 알 수 있지만, 원래 객체를 파괴하면 일반적인 값 객체 할당과 마찬가지로 약한 참조 객체도 파괴됩니다. 이전 기사를 읽지 않았거나 PHP 참조에 익숙하지 않은 경우 PHP 참조에 대해 자세히 알아봐야 할 수도 있습니다. 아래에서는 예시를 통해 직접 살펴보겠습니다.
WeakReference
$obj = new stdClass; $weakref = $obj; var_dump($weakref); // object(stdClass)#1 (0) { // } unset($obj); var_dump($weakref); // object(stdClass)#1 (0) { // } $obj1 = new stdClass; $weakref = WeakReference::create($obj1); var_dump($weakref->get()); // object(stdClass)#2 (0) { // } unset($obj1); var_dump($weakref->get()); // NULL $weakref = WeakReference::create(new stdClass); var_dump($weakref->get()); // NULL
첫 번째 객체 $obj에서는 PHP의 기본 객체 할당인 직접 할당 참조를 수행합니다. 현재 $weakref는 객체 기호 테이블에 대한 참조를 보유합니다. $obj를 unset()해도 $weakref는 여전히 정상적으로 사용될 수 있습니다. 즉, 원본 개체 $obj에 대한 $weakref의 메모리 참조가 여전히 남아 있습니다. 원본 $obj를 어떻게 unset()하더라도 $obj의 참조 기호 테이블만 잘라내고 실제 객체에는 아무런 영향을 미치지 않습니다. 가비지 수집기는 원본 $obj 객체의 내용을 완전히 재활용하지 않습니다.
두 번째 객체의 경우 WeakReference의 create() 메서드를 사용하여 약한 참조를 생성합니다. $obj1을 삭제하면 $weakref도 NULL이 됩니다. 이것이 약한 참조의 목적입니다!
가비지 수집기가 정상적으로 재활용되도록 하고, 순환 참조로 인한 메모리 누수 문제를 피할 수 있으며, 참조가 C의 포인터 작업처럼 동작하도록 할 수 있습니다.
코드의 마지막 부분은 객체를 생성하기 위해 WeakReference::create()에서 직접 new를 사용한다는 것입니다. 이 형식은 불가능하며 항상 NULL을 반환합니다. 약한 참조는 변수를 통해 생성되기 때문에 원래 객체의 심볼 테이블을 가리키며, 변수와 객체 사이의 심볼 테이블 연결은 약한 참조가 신경쓰는 상태에 따라 현재 상태를 판단하게 됩니다. 기호 테이블의 . 원래 개체 변수가 기호 테이블에서 잘려지면 약하게 참조된 변수도 동기식으로 잘려서 가비지 수집기가 더 이상 참조 횟수가 없는 개체를 정상적으로 정리할 수 있습니다.
Note
여기서 위의 테스트 코드는 PHP7.4 이상에서 사용해야 한다는 점에 유의해야 합니다. WeakReference 클래스는 PHP7.4에 새로 추가되었습니다. 이전 버전에서는 약한 참조 기능을 구현하려면 WeakRef 확장을 설치해야 했습니다. 구체적인 내용은 아래 링크의 관련 문서를 참조하세요.
테스트 코드:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202006/source/%E5%AD%A6%E4%B9%A0PHP%E5%BC%B1%E5%BC%95%E7%94%A8%E7%9A%84%E7%9F%A5%E8%AF%86.php
추천 학습: "PHP 비디오 튜토리얼"