ProgramlamaBackend geliştirici

Rust'ta akıllı işaretçiler (Box, Rc, Arc, RefCell) nasıl çalışır? Birbirlerinden ne ile farklıdırlar ve hangi durumda hangisini seçmek gerekir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap

Rust'ta klasik bir çöp toplayıcı yoktur, bu nedenle karmaşık yapıların sahipliğini yönetmek için akıllı işaretçiler (smart pointers) kullanılır. En sık kullanılanlar şunlardır:

  • Box<T> — nesne için bellek ayırır ve sahipliği devreder. Derleme sırasında verilerin boyutu bilinmediğinde veya taşınabilir ama benzersiz bir kaynağa ihtiyaç duyulduğunda kullanılır.

  • Rc<T> (Referans Sayımlı) — referans sayımı yapar, birden fazla değişkenin değiştirilemez veriler üzerinde sahipliği "paylaşmasına" izin verir (sadece tek iş parçacıklı bağlamda).

  • Arc<T> (Atomik Referans Sayımlı) — aynı zamanda referans sayımı yapar, ancak atomiktir; çok iş parçacıklı programlarda kullanılabilir.

  • RefCell<T> — çalışma zamanında "içsel değiştirilebilir" sahiplik sağlar, değiştirilemez bir referans aracılığıyla bile içerikleri değiştirmeye izin verir, ancak sadece bir iş parçacığında (iş parçacığı güvenli değildir!).

Örnek:

use std::rc::Rc; let a = Rc::new(vec![1,2,3]); let b = Rc::clone(&a); // Artık hem a hem de b aynı verilere sahiptir

Kandırmaca Sorusu

Tüm iş parçacıkları yalnızca verileri okursa, Rc<T> çok iş parçacıklı kodda kullanılabilir mi? Açıklayın.

Cevap: Hayır, kullanılamaz! Rc<T> yalnızca verilere değiştirilemez erişim sağlasa da, Rc<T> konteynerinin kendisi iş parçacığı güvenli değildir, çünkü içteki referans sayısı veri yarışlarına karşı korunmaz. Bunun için Arc<T> tasarlanmıştır — içteki sayacı iş parçacığı güvenlidir.

Örnek:

// Aşağıdaki kod derlenmeyecek! use std::thread; use std::rc::Rc; let five = Rc::new(5); for _ in 0..10 { let five = Rc::clone(&five); thread::spawn(move || { println!("{}", five); }); }

Konunun inceliklerini bilmemekten kaynaklanan gerçek hata örnekleri


Hikaye

Web hizmetini hızlandırmak için iş parçacıkları arasında bir önbelleği paylaşmak için Rc<T> kullanmaya çalıştık. Üretimde tuhaf çökme ve bozulmuş veriler aldık. Araştırma sonucunda Rc'nın iş parçacığı güvenli olmadığı ve referans sayısının bozulduğu ortaya çıktı. Çözüm: Arc<T> ile değiştirme.

Hikaye

Masaüstü uygulamasında büyük bir nesne ağacını Box<T> içinde sakladık, ancak UI'nin birkaç parçasının veriler üzerinde sahipliği paylaşması gerektiğini dikkate almadık. Bu derleme hatalarına yol açtı. Çözüm, erişimi paylaşmak için Rc<T> kullanmak oldu.

Hikaye

İş mantığı modülünde RefCell<T> kullanarak Arc<T> aracılığıyla iş parçacıkları arasında da iletilen verilere değiştirilebilir erişim sağlamaya çalıştık. Ancak RefCell<T> ile Arc<T> kombinasyonu yarışmalara ve çalıştırma sırasında paniğe yol açtı. İş parçacığı güvenli bir seçenek için RefCell<T> yerine Mutex<T> veya RwLock<T> kullanmak gerekir.