Konunun Tarihi:
Thread desteği Perl 5.005'te ortaya çıkmıştır, ancak dilin uygulanmasındaki özellikler nedeniyle uzun süre deneme aşamasında kalmış ve birçok hata ve kısıtlama ile birlikte gelmiştir. Perl 5.8'den itibaren, threads (ve threads::shared) modülü ciddi görevler için yeterince stabil hale gelmiştir, ancak Perl'in thread modeli birçok diğer programlama dillerinden önemli ölçüde farklıdır: her thread, tüm değişkenlerin kendi kopyasını alır ve yalnızca açıkça tanımlanan yapılar üzerinden threads::shared ile ortak erişime açıktır.
Sorun:
"Normal" değişkenler, copy-on-write mantığı nedeniyle threadler arasında görünmez. threads::shared olmadan veri dağıtımı, durumun senkronizasyonunu kaybetmeye neden olur. Kilitlerin hatalı kullanımı yarış koşulları, kilitlenmeler veya tutarsız değişiklikler tehlikesi doğurur.
Çözüm:
Ortak değişkenlerin kullanımı için use threads::shared ile shared değişkenler tanımlayın. Aynı anda birden fazla thread okuma/yazma yapıyorsa, shared verilere erişimi lock ile kilitleyin. Thread'lerin yaşam döngüsünü yönetmek için join/detach yöntemlerini kullanın. Karmaşık yapılarda her bir öğeyi ayrı ayrı shared olarak tanımlayın, çünkü yalnızca "üst seviye" tam thread güvenliği sağlamaz.
Kod Örneği:
use threads; use threads::shared; my $counter :shared = 0; my @threads; for (1..10) { push @threads, threads->create(sub { for (1..1000) { lock($counter); ++$counter; } }); } $_->join() for @threads; print "Counter: $counter ";
Anahtar Özellikler:
:shared, ek bir lock olmadan thread güvenliği sağlar mı?
Hayır. :shared niteliği, bir değişkene threadler arasında erişim sağlar, ancak değişiklikler (örneğin, ++ veya --) atomik değildir. Kritik her bölüm için lock gereklidir.
Threadler arasında karmaşık bir yapıyı (hash dizisi) tek bir :shared direktifi ile paylaşmak mümkün müdür?
Hayır. Sadece dizinin veya hashın "üst seviyesi" shared olacaktır. Her bir iç öğenin de shared yapılması gerekir, aksi halde iç yapılar diğer threadler tarafından görünmez.
Bir thread, exit çağrısıyla diğer bir thread'i öldürebilir mi?
Hayır. exit, sürecin tamamını durdurur, yalnızca bir thread'i değil. Bir thread'i durdurmak, ya thread içinde exit ile ya da join/detach mantığı ile yönetilir.
İki thread aynı anda $counter :shared'i kilitsiz artırır. Sonuç, beklenenden daha azdır (tipik bir kaybolan güncelleme sorunu).
Artılar:
Eksiler:
Paylaşılan değişkenin her değişiminde lock uygulanması. Büyük yapılarda iç içe lock, öğe bazında.
Artılar:
Eksiler: