Anda benar. Bentuk spesifik pengumpulan sampah yang Anda gambarkan disebut " penghitungan referensi ". Cara kerjanya (secara konseptual, setidaknya, sebagian besar implementasi modern penghitungan referensi sebenarnya diimplementasikan dengan sangat berbeda) dalam kasus yang paling sederhana, terlihat seperti ini:
- setiap kali referensi ke objek ditambahkan (misalnya ditugaskan ke variabel atau bidang, diteruskan ke metode, dan sebagainya), jumlah referensi meningkat sebesar 1
- setiap kali referensi ke suatu objek dihapus (metode kembali, variabel keluar dari lingkup, bidang ditugaskan kembali ke objek yang berbeda atau objek yang berisi bidang itu sendiri mengumpulkan sampah), jumlah referensi berkurang 1
- segera setelah jumlah referensi mencapai 0, tidak ada lagi referensi ke objek, yang berarti tidak ada yang dapat menggunakannya lagi, oleh karena itu adalah sampah dan dapat dikumpulkan
Dan strategi sederhana ini memiliki masalah yang Anda jelaskan: jika A referensi B dan B referensi A, maka kedua jumlah referensi mereka tidak akan pernah kurang dari 1, yang berarti mereka tidak akan pernah dikumpulkan.
Ada empat cara untuk mengatasi masalah ini:
- Abaikan itu. Jika Anda memiliki cukup memori, siklus Anda kecil dan jarang dan runtime Anda pendek, mungkin Anda bisa lolos dengan tidak mengumpulkan siklus. Pikirkan juru bahasa skrip shell: skrip shell biasanya hanya berjalan selama beberapa detik dan tidak mengalokasikan banyak memori.
- Gabungkan referensi Anda menghitung pengumpul sampah dengan pengumpul sampah lain yang tidak memiliki masalah dengan siklus. CPython melakukan ini, misalnya: pengumpul sampah utama di CPython adalah pengumpul penghitungan referensi, tetapi dari waktu ke waktu pengumpul sampah penelusuran dijalankan untuk mengumpulkan siklus.
- Deteksi siklusnya. Sayangnya, mendeteksi siklus dalam grafik adalah operasi yang agak mahal. Secara khusus, ini membutuhkan biaya overhead yang hampir sama dengan kolektor pelacak, jadi Anda bisa menggunakan salah satunya.
- Jangan menerapkan algoritme dengan cara naif seperti Anda dan saya: sejak tahun 1970-an, ada beberapa algoritma yang cukup menarik yang dikembangkan yang menggabungkan deteksi siklus dan penghitungan referensi dalam satu operasi dengan cara yang pintar yang secara signifikan lebih murah daripada melakukannya baik secara terpisah atau melakukan tracing collector.
Ngomong-ngomong, cara utama lainnya untuk mengimplementasikan pengumpul sampah (dan saya sudah mengisyaratkan bahwa beberapa kali di atas), sedang melacak . Seorang kolektor tracing didasarkan pada konsep reachability . Anda mulai dengan beberapa set root yang Anda tahu selalu dapat dijangkau (konstanta global, misalnya, atau Object
kelas, ruang lingkup leksikal saat ini, bingkai stack saat ini) dan dari sana Anda melacak semua objek yang dapat dijangkau dari set root, kemudian semua objek yang dapat dijangkau dari objek yang dapat dijangkau dari root set dan seterusnya, sampai Anda memiliki penutupan transitif. Segala sesuatu yang tidak ada dalam penutupan itu adalah sampah.
Karena sebuah siklus hanya dapat dicapai dalam dirinya sendiri, tetapi tidak dapat dicapai dari set root, itu akan dikumpulkan.