Bölüm 7: Kilitlenme
Giriş
Öğrenme Çıktıları
Kilitlenmeyi tanımlamak; kesilebilir ve kesilemez kaynakları, istek–kullanım–bırakma döngüsünü ayırt etmek.
Coffman koşullarını (karşılıklı dışlama, tut ve bekle, kesme yok, döngüsel bekleme) bir örnek üzerinde göstermek.
Kaynak tahsis ve bekleme çizgelerini çizmek; döngünün ne zaman kilitlenme anlamına geldiğini söylemek.
Matris tabanlı tespit algoritmasını elle çalıştırmak; kesme, geri sarma ve sonlandırma ile kurtarmayı karşılaştırmak.
Güvenli ve güvensiz durumları ayırt etmek; Bankacı algoritmasıyla bir isteğin verilip verilmeyeceğine karar vermek.
Kilit sıralaması, iki aşamalı kilitleme, canlı kilit ve açlığı tanımak; Java'da kilitlenmeyi jstack ile bulmak.
Giriş
Kilitlenme Nedir?
- Tanım (Tanenbaum): bir süreç kümesindeki her süreç, yalnızca kümedeki başka bir sürecin tetikleyebileceği bir olayı bekliyorsa küme kilitlenmiştir (deadlock).
- Beklenen olay çoğunlukla bir kaynağın serbest bırakılmasıdır; hiçbiri çalışmadığından hiçbiri bırakamaz.
- Örnek: S1, K1'i tutup K2'yi bekler; S2, K2'yi tutup K1'i bekler.
- Gündelik örnek: kavşakta dört araç birbirinin önünü keser (gridlock); tek hatlı rayda karşılıklı iki tren.
- Kilitlenen süreçler CPU harcamaz (bloke olmuşlardır) ama tuttukları kaynaklar sonsuza dek kullanılamaz.
Konu yalnızca işletim sistemi değil: veritabanı işlemleri, çok iş parçacıklı uygulamalar ve dağıtık sistemler de kilitlenir.
Giriş
Kaynaklar: Kesilebilir ve Kesilemez
Sahibinden zarar vermeden geri alınabilir. Örnek: CPU (bağlam kaydedilir), ana bellek (sayfa diske yazılır). Kilitlenme, kaynağı yeniden dağıtarak çözülebilir.
Geri almak işlemi bozar. Örnek: yazılmakta olan Blu-ray/yazıcı işi, bir mutex, veritabanı kaydı kilidi. Kilitlenmeler bu tür kaynaklarla ilgilidir.
| Kaynak | Örnek sayısı | Tür | Not |
|---|---|---|---|
| CPU çekirdeği | çok | kesilebilir | zamanlayıcı kesmesiyle el değiştirir |
| Bellek sayfası | çok | kesilebilir | takas/sayfalama ile geri alınır |
| Mutex, semafor, dosya kilidi | 1 | kesilemez | yalnızca sahibi bırakır |
| Veritabanı satır kilidi | 1 | kesilemez* | *işlem geri sarılırsa (abort) bırakılır |
Her kaynak türü Ri'nin Wi tane özdeş örneği (instance) olabilir; bir istek o türün herhangi bir örneğiyle karşılanabiliyorsa örnekler özdeştir.
Giriş
Kaynak Kullanım Döngüsü
- İste (request): kaynak boştaysa verilir; değilse süreç bloke olur (ya da hata kodu alıp sonra yeniden dener).
- Kullan (use): süreç kaynak üzerinde işlem yapar.
- Bırak (release): kaynak serbest kalır, bekleyenlerden biri uyandırılır.
- İşletim sistemi bir sistem tablosunda hangi kaynağın kime verildiğini ve kimin beklediğini tutar.
| İste | Bırak |
|---|---|
open() | close() |
malloc() / mmap() | free() / munmap() |
pthread_mutex_lock() | pthread_mutex_unlock() |
sem_wait() (down) | sem_post() (up) |
Giriş
Aynı Sıra ve Ters Sıra
Her kaynak bir ikili semaforla korunur: erişmeden önce down, iş bitince up. Tek süreç ya da tek kaynak varken sorun yoktur.
Kilitlenmez: ikisi de önce 1, sonra 2
void process_A(void) { down(&resource_1); down(&resource_2); use_both_resources(); up(&resource_2); up(&resource_1); } void process_B(void) { down(&resource_1); down(&resource_2); use_both_resources(); up(&resource_2); up(&resource_1); }
Kilitlenebilir: B önce 2, sonra 1
void process_A(void) { down(&resource_1); down(&resource_2); use_both_resources(); up(&resource_2); up(&resource_1); } void process_B(void) { down(&resource_2); /* ters sıra */ down(&resource_1); use_both_resources(); up(&resource_1); up(&resource_2); }
Giriş · Kodu adım adım çalıştır
Ters Sırada Edinim: Adım Adım
semaphore r1 = 1, r2 = 1; void A(void) { down(&r1); down(&r2); use_both(); up(&r2); up(&r1); } void B(void) { down(&r2); down(&r1); use_both(); up(&r1); up(&r2); }
İki ikili semafor 1 ile başlar: iki kaynak da boş.
A down(&r1) yapar ve r1'i alır (r1 → A kenarı).
Zamanlayıcı B'ye geçer; B down(&r2) ile r2'yi alır.
B r1'i ister; r1 A'da olduğu için B bloke olur (kesikli istek kenarı).
A r2'yi ister; r2 B'de, A da bloke olur.
Çizgede döngü oluştu. up satırlarına hiçbiri ulaşamaz: kilitlenme.
Kilitlenme her çalıştırmada oluşmaz: A iki down'u B başlamadan bitirirse sorun çıkmaz. Bu yüzden testte nadiren görülür, üretimde ortaya çıkar.
Kilitlenme Koşulları
Kilitlenmenin Dört Koşulu (Coffman, 1971)
Kaynak ya tam olarak bir sürece atanmıştır ya da boştur; aynı anda paylaşılamaz.
Bir süreç en az bir kaynağı tutarken başkasının tuttuğu yeni kaynakları ister ve bekler.
Verilmiş bir kaynak zorla geri alınamaz; yalnızca tutan süreç kendi isteğiyle bırakır.
T0, T1'in; T1, T2'nin; …; Tn, T0'ın tuttuğu kaynağı bekler.
Kilitlenme Koşulları
Dört Koşul Bir Arada
- Kavşağın dört karesi = dört kesilemez kaynak; araçlar = süreçler.
- Her adımda bir koşulu işaretleyin.
- Herhangi bir koşulu kırmak çözümdür:
- trafik polisi bir aracı geri çektirir (kesme),
- “kavşak boşalmadan girme” kuralı (tut ve bekle yok),
- trafik ışığı (sıralama, döngü yok).
Karşılıklı dışlama: bir kavşak karesinde aynı anda yalnızca bir araç bulunabilir.
Tut ve bekle: her araç bulunduğu kareyi tutarken önündeki kareyi bekliyor (turuncu oklar).
Kesme yok: arkada kuyruk var; hiçbir araç kareyi boşaltmak için geri çekilemez.
Döngüsel bekleme: A → B → C → D → A. Dört koşul birlikte: trafik kilitlendi.
Modelleme
Kaynak Tahsis Çizgesi
- Holt (1972): iki tür düğüm; süreçler daire, kaynaklar kare. Çok örnekli kaynakta karenin içinde her örnek için bir nokta.
- Atama kenarı R → P: R, P'ye verilmiş. İstek kenarı P → R: P, R'yi bekliyor (bu sunumda kesikli turuncu).
- İstek karşılandığında istek kenarı atama kenarına dönüşür; bırakıldığında silinir.
Tanenbaum MOS Şekil 6-3. Silberschatz aynı modeli “resource-allocation graph” olarak T (thread) düğümleriyle çizer.
Modelleme
Kilitlenme Nasıl Oluşur?
A B C R iste S iste T iste S iste T iste R iste R bırak S bırak T bırak S bırak T bırak R bırak
İşletim sistemi istekleri geldiği sırada karşılarsa: R, S, T verilir, sonra her süreç bir sonrakinin kaynağını ister.
Başlangıç: üç kaynak da boş. Sıralı (round-robin) zamanlama varsayılıyor.
1. A, R'yi ister ve alır.
2. B, S'yi ister ve alır.
3. C, T'yi ister ve alır.
4. A, S'yi ister: S, B'de → A bloke.
5. B, T'yi ister: T, C'de → B bloke.
6. C, R'yi ister: R, A'da → C bloke. Döngü kapandı: kilitlenme.
Tanenbaum MOS Şekil 6-4 (a)–(j). Gerçekte zamanlayıcı başka bir sıra da seçebilirdi; kilitlenme sıralamaya bağlıdır.
Modelleme
Kilitlenme Nasıl Önlenebilir?
A B C R iste S iste T iste S iste T iste R iste R bırak S bırak T bırak S bırak T bırak R bırak
İS, bir isteği vermenin kilitlenmeye yol açacağını önceden bilseydi, B'yi bekleterek tehlikeli sırayı engelleyebilirdi.
İS, B'nin isteklerini bir süre askıya alır (B'yi zamanlamaz). Sadece A ve C çalışır.
1. A, R'yi ister ve alır.
2. C, T'yi ister ve alır.
3. A, S'yi ister ve alır (S boş).
4. C, R'yi ister: R, A'da → C bloke. Döngü yok, A ilerleyebilir.
5. A, R'yi bırakır → R, C'ye verilir; C ilerler.
6. A, S'yi bırakıp biter. Artık B çalıştırılabilir: S'yi alır, T'yi C bitince alır. Kilitlenme yok.
Tanenbaum MOS Şekil 6-4 (k)–(q). “Hangi isteği ertelemeli?” sorusu, ilerideki kaçınma (Bankacı algoritması) konusunun özüdür.
Modelleme
Çok Örnekli Kaynaklar
- Kaynak kümeleri: R1 ×1, R2 ×2, R3 ×1, R4 ×3.
- T1: bir R2 örneğini tutar, R1'i bekler.
- T2: R1'i ve bir R2 örneğini tutar, R3'ü bekler.
- T3: R3'ü tutar.
- Atama kenarı karedeki noktadan (örnekten) çıkar; istek kenarı karenin kendisine gider.
- Çizgede döngü yok → kilitlenme yok: T3 bitince R3'ü bırakır, T2 sonra T1 ilerler.
Silberschatz 10e Şekil 8.4. R4'ün üç örneği de boşta.
Modelleme
Döngü ve Kilitlenme
- Tek bir istek kenarı (T3 → R2) iki döngü oluşturur.
- T3, T1 ya da T2'nin bir R2 bırakmasını bekler; T2, T3'ün R3'ünü; T1, T2'nin R1'ini.
- Döngüdeki her süreç döngüdeki bir başkasını bekliyor ve dışarıdan bir “kurtarıcı” yok.
Önceki durum: döngü yok.
T3, bir R2 örneği ister. İki örnek de dolu (T1 ve T2'de) → T3 bloke.
Döngü 1: T1 → R1 → T2 → R3 → T3 → R2 → T1.
Döngü 2: T2 → R3 → T3 → R2 → T2. R2'nin her iki örneğinin sahibi de döngüde → kilitlenme.
Silberschatz 10e Şekil 8.5.
Modelleme
Döngü Var, Kilitlenme Yok
- Kaynak türlerinin birden çok örneği varsa döngü gerekli ama yeterli değildir.
- Döngü dışındaki bir süreç (T2 ya da T4) bitip örneğini bırakınca döngü çözülür.
- Bu yüzden çok örnekli durumda çizgede döngü aramak yetmez; matris tabanlı bir algoritma gerekir.
T1 bir R1 ister; R1'in iki örneği T2 ve T3'te. T3 bir R2 ister; R2'nin örnekleri T1 ve T4'te.
Döngü var: T1 → R1 → T3 → R2 → T1. Ama T2 ve T4 döngünün dışında ve hiçbir şey beklemiyor.
T4 işini bitirip R2 örneğini bırakır → örnek T3'e verilir. Döngü kırıldı: kilitlenme yoktu.
Silberschatz 10e Şekil 8.6.
Modelleme
Döngü Kuralı
| Çizge | Her kaynak türünde tek örnek | Bazı türlerde birden çok örnek |
|---|---|---|
| Döngü yok | Kilitlenme yok | Kilitlenme yok |
| Döngü var | Kilitlenme var (döngü ⇔ kilitlenme) | Kilitlenme olabilir; döngü gerekli ama yeterli değil |
Döngü arama yeterli: DFS ile O(V + E). Döngüdeki süreçler kilitlenmiştir.
Döngü yalnızca bir uyarıdır. Kesin karar için tahsis/istek matrisleriyle “herkes bitebilir mi?” diye sorulur.
Döngüsel bekleme koşulu, döngü içeren çizgenin karşılığıdır; tek örnekli kaynaklarda dört koşulun birlikte varlığı kilitlenmeyi garanti eder.
Modelleme
Bekleme (Wait-For) Çizgesi
Tek örnekli kaynaklarla bir tahsis çizgesi: P1 R1'i tutar R2'yi ister, P2 R2'yi tutar R3'ü ister, P3 R3'ü tutar R1'i ister, P4 R4'ü tutar R2'yi ister.
Her Pi → R → Pj yolu tek bir Pi → Pj kenarına daraltılır (kırmızı): “Pi, Pj'yi bekliyor”.
Kaynak düğümleri silinir: bekleme (wait-for) çizgesi.
Bekleme çizgesinde döngü ⇔ kilitlenme. Algoritma çizgeyi periyodik tarar; maliyet O(n²) (n: süreç sayısı).
Yalnızca her türden tek örnek olduğunda kullanılabilir. Veritabanları (ör. PostgreSQL, MySQL InnoDB) kilit bekleme çizgesinde döngü arayarak kilitlenme tespit eder.
Stratejiler
Kilitlenmelerle Başa Çıkma Stratejileri
“Devekuşu algoritması”. Kilitlenme nadir ve önleme maliyeti yüksekse sorunu yok sayıp gerekirse yeniden başlat. Linux ve Windows genel kaynaklar için bunu yapar.
Tepkisel. Kilitlenmeye izin ver, periyodik olarak tespit et, sonra kesme, geri sarma ya da sonlandırma ile çöz.
Önleyici, çalışma anında. Her isteği, sistemi güvensiz duruma sokacaksa ertele (Bankacı). Azami ihtiyaçların önceden bilinmesini ister.
Önleyici, tasarım anında. Dört koşuldan en az birini yapısal olarak imkânsız kıl (ör. kilit sıralaması).
Eski sunumda “kurtarma” ayrı bir dördüncü teknik olarak sayılıyordu; kurtarma, tespitin ikinci yarısıdır. Görmezden gelme ise listede eksikti.
Stratejiler
Devekuşu Algoritması
- Strateji: hiçbir şey yapma. Kilitlenme olursa kullanıcı/yönetici süreci öldürür ya da sistemi yeniden başlatır.
- Mühendislik dengesi: kilitlenme yılda bir kez oluyor, çökmeler ve donanım hataları ise çok daha sık görülüyorsa, pahalı ve kısıtlayıcı önlemler değmez.
- Genel amaçlı İS'ler (Linux, Windows, macOS) kullanıcı süreçlerinin kilitleri, dosya kilitleri, boru (pipe) beklemeleri için bunu uygular; sorumluluk uygulama geliştiricisindedir.
- Ama İS kendi içinde kilitlenmeye karşı önlem alır: çekirdek kilit sıralaması,
lockdepdenetimi. - Gerçek zamanlı ve güvenlik-kritik sistemlerde kabul edilemez.
Tespit ve Kurtarma
Tespit: Her Türden Tek Kaynak
- A: R'yi tutar, S'yi ister. B: T'yi ister.
- C: S'yi ister. D: U'yu tutar, S ve T'yi ister.
- E: T'yi tutar, V'yi ister. F: W'yi tutar, S'yi ister.
- G: V'yi tutar, U'yu ister.
- Soru: sistem kilitlenmiş mi, kilitlendiyse hangi süreçler?
- Çizgede döngü: D → T → E → V → G → U → D. D, E, G kilitli.
- A, C, F kilitli değil: S boşta; biri alır, bitirir, bırakır. B ise döngüdeki T'yi beklediği için ilerleyemez (döngüde olmasa da takılı).
Tanenbaum MOS Şekil 6-5. Göz ile kolay; yüzlerce düğümlü bir çizgede sistematik bir algoritma gerekir.
Tespit ve Kurtarma
Döngü Arama Algoritması (DFS)
- Çizgedeki her N düğümü için 2–6. adımları N'den başlayarak uygula.
- L'yi boş liste yap; tüm kenarları işaretsiz say.
- Geçerli düğümü L'nin sonuna ekle. Düğüm L'de iki kez geçiyorsa çizgede döngü vardır: L'deki döngüyü raporla, dur.
- Geçerli düğümden çıkan işaretsiz kenar var mı? Varsa 5'e, yoksa 6'ya git.
- Rastgele bir işaretsiz kenar seç, işaretle, gösterdiği düğüme geç; 3'e dön.
- Başlangıç düğümündeysek bu N'den erişilebilen döngü yoktur. Değilsek çıkmaz sokaktayız: düğümü L'den çıkar, önceki düğüme dön, 3'e git.
Her düğümden başlayan bir derinlik öncelikli arama; yığın görevini L listesi görür.
Basit sürüm her düğümden yeniden başladığı için O(V·(V+E)); renkli DFS (beyaz/gri/siyah) tek geçişte O(V+E).
L'nin tekrar eden düğümden sonraki kısmı döngüdür; içindeki süreçler kilitlenmiştir.
Tespit ve Kurtarma
Döngü Arama: Adım Adım
- Düğümler alfabetik sırayla başlangıç alınır: R, A, B, …
- Turuncu düğümler o anki L listesinde; kırmızı çerçeve geçerli düğüm.
- Kenar seçimi “rastgele” olabilir; burada önce S, sonra T seçiliyor.
R'den başla. L = [R]. Tek çıkış R → A.
R → A → S. S'den çıkan kenar yok: çıkmaz sokak.
S, sonra A ve R L'den çıkarılır; R'ye dönüldü: R'den döngü yok. Sonra A'dan başlanır (yine yok)…
B'den başla: B → T → E.
E → V → G → U. Hâlâ tekrar yok.
U → D. D'den önce S denenir: çıkmaz sokak, S L'den çıkar.
D → T: T, L'de ikinci kez → döngü: T, E, V, G, U, D. Algoritma durur.
Tespit ve Kurtarma
Tespit: Her Türden Çok Kaynak
- n süreç, m kaynak türü. C'nin i. satırı Pi'nin şu an tuttuğu, R'nin i. satırı Pi'nin şu an istediği kaynaklardır.
- Vektör karşılaştırması: X ≤ Y ancak ve ancak her j için Xj ≤ Yj. Ör. (1 0 1 0) ≤ (2 1 0 0) değil.
Tanenbaum MOS Şekil 6-6. Silberschatz aynı yapıları Available, Allocation, Request adlarıyla verir.
Tespit ve Kurtarma
Tespit Algoritması
A ← boş kaynak vektörü
tüm Pi işaretsiz
tekrarla:
Ri ≤ A olan işaretsiz bir Pi bul
bulunamazsa: çık
A ← A + Ci /* Pi biter, bırakır */
Pi'yi işaretle
işaretsiz Pi'ler kilitlenmiştir- Fikir: isteği şu anki boş kaynaklarla karşılanabilen bir süreç bitebilir; bitince tuttuklarını geri verir.
- Bu iyimser bir varsayımdır: süreç ek kaynak istemeden bitecek sayılır. Yanılırsa sonraki çalıştırmada yakalanır.
- Sonda işaretsiz kalanlar kilitlenmiştir.
- Karmaşıklık: O(m · n²).
Tespit ve Kurtarma · Algoritmayı adım adım çalıştır
Tespit Örneği
A ← (2 1 0 0) tüm Pi işaretsiz tekrarla: Ri ≤ A olan işaretsiz Pi bul bulunamazsa: çık A ← A + Ci Pi'yi işaretle işaretsizler kilitli
Teyp (Tp), çizici (Pl), tarayıcı (Tr), CD. E = (4 2 3 1), boşta A = (2 1 0 0).
P1: R₁ = (2 0 0 1). Boş CD yok → şimdilik bitemez.
P2: R₂ = (1 0 1 0). Boş tarayıcı yok ✗.
P3: R₃ = (2 1 0 0) ≤ A ✓. P3 çalışıp bitebilir.
P3 biter, tuttuğu C₃ = (0 1 2 0) geri gelir: A = (2 2 2 0).
Yeni tur. P1 yine bekler (CD = 0).
P2: (1 0 1 0) ≤ (2 2 2 0) ✓ → biter, C₂ = (2 0 0 1) döner: A = (4 2 2 1).
P1: (2 0 0 1) ≤ (4 2 2 1) ✓ → biter: A = (4 2 3 1) = E.
Tüm süreçler işaretlendi: kilitlenme yok.
Tanenbaum MOS Şekil 6-7. Bulunan sıra (P3, P2, P1), algoritmanın satırları hangi sırayla taradığına bağlıdır; sonuç değişmez.
Tespit ve Kurtarma
Bir İstek Fazlası: Kilitlenme
- Tek bir hücrenin (R₃'teki CD) değişmesi sonucu tamamen değiştirir.
- İlk turda hiçbir satır karşılanamazsa algoritma hemen biter.
- Çok örnekli kaynakta çizge yerine bu tarama kullanılır; döngü bilgisi kendiliğinden gelir.
Aynı durum, tek fark: P3 iki teyp ve bir çiziciye ek olarak bir CD de istiyor: R₃ = (2 1 0 1).
P1 ✗ (CD gerekli, boşta yok).
P2 ✗ (tarayıcı gerekli, boşta yok).
P3 ✗ (CD tek ve P2'de). Hiçbir satır karşılanamıyor: üç süreç de kilitlenmiş.
Tespit ve Kurtarma
Tespit Ne Zaman Çalıştırılmalı?
Bekletilen her istekten sonra. Kilitlenme anında, suçlu istekle birlikte bulunur; ama CPU maliyeti yüksektir.
Her k dakikada bir. Ucuzdur; kilitlenme bir süre fark edilmeden kalır, döngüye başka süreçler de takılabilir.
CPU kullanımı belirli bir eşiğin altına düştüğünde ya da bir kilit beklemesi uzadığında.
- Ne sıklıkla? Kilitlenmenin ne kadar olası olduğuna ve kaç sürecin etkileneceğine bağlı.
- Örnek: PostgreSQL bir kilidi
deadlock_timeout(varsayılan 1 sn) kadar bekleyen işlem için bekleme çizgesini tarar; döngü bulursa bir işlemi iptal eder (ERROR: deadlock detected). - Eski sunumda tespit için “önemli bir yük getirmez” deniyordu: yük, çalıştırma sıklığıyla doğru orantılıdır; ayrıca kurtarmanın maliyeti (kaybolan iş) de hesaba katılmalıdır.
Tespit ve Kurtarma
Kilitlenmeden Kurtarma
Bir kaynağı sahibinden geçici olarak alıp başka sürece ver (ör. yazıcı işini kenara alıp kâğıtları ayırmak). Kaynağın doğasına bağlı; çoğu zaman elle ya da imkânsız.
Süreçler periyodik olarak denetim noktası (checkpoint) kaydeder. Kurban, kaynağı almadan önceki noktaya döndürülür; sonraki iş kaybolur. Veritabanlarında işlem iptali (abort) budur.
En kaba yöntem. Ya döngüdeki tüm süreçler ya da döngü kırılana kadar teker teker (her öldürmeden sonra tespit yeniden çalışır). Döngü dışından bir süreç de seçilebilir.
Kurban seçimi (en düşük maliyet): öncelik, ne kadar çalıştığı ve ne kadar kaldığı, tuttuğu kaynak sayısı, bitmek için kaç kaynak daha istediği, etkileşimli mi toplu mu, yeniden başlatılabilir mi (ör. derleme evet, veritabanı güncellemesi dikkat). Aynı süreç sürekli kurban seçilirse açlık: geri sarma sayısını maliyete ekle.
Tespit ve Kurtarma
Kurtarma: Adım Adım
Tespit algoritması P1 → R2 → P2 → R3 → P3 → R1 → P1 döngüsünü buldu. P4 de R2'yi beklediği için takılı.
Kurban: en az iş kaybettirecek süreç, P3. Sonlandırılır (ya da denetim noktasına geri sarılır); tuttuğu R3 serbest kalır.
R3 bekleyen P2'ye verilir. P2 işini bitirip R2 ve R3'ü bırakır.
R2 sıradaki bekleyene (P1) verilir; P1 bitince P4. P3 baştan (ya da denetim noktasından) yeniden çalıştırılır.
Teker teker sonlandırmada her kurbandan sonra tespit algoritması yeniden çalışır; döngü kırılınca durulur.
Kaçınma
Kaynak Yörüngeleri
- A: I1–I3 arası yazıcı, I2–I4 arası çizici kullanır.
- B: I5–I7 arası çizici, I6–I8 arası yazıcı kullanır.
- Taralı bölgeler karşılıklı dışlama nedeniyle girilemez.
- Kaçınma = yörüngeyi güvensiz bölgeye sokacak isteği ertelemek.
Yatay eksen A'nın, dikey eksen B'nin yürüttüğü komutlar. Tek CPU: yörünge yalnızca sağa (A çalışır) ya da yukarı (B çalışır) ilerler.
p → q: A çalışır; q → r: B çalışır; r → s: A yazıcıyı alır (I1). s → t: B ilerler, I5'te çiziciyi isteyecek.
Kırmızı kutuya girilirse A yazıcıyı, B çiziciyi tutar ve ikisi de taralı bölgeye girmek zorundadır: kilitlenme kaçınılmaz. Bu bölge güvensizdir.
t noktasında İS, B'nin çizici isteğini erteler; A I4'e kadar çalışıp ikisini de bırakır. Sonra B devam eder: kilitlenme yok.
Tanenbaum MOS Şekil 6-8 (Dijkstra'nın iki süreçli gösterimi).
Kaçınma
Güvenli ve Güvensiz Durumlar
- Durum: E, A, C ve azami ihtiyaçlar (Max) ile belirlenir.
- Güvenli durum: her süreç anında azami isteğini yapsa bile, tüm süreçleri bir sırayla sonuna kadar çalıştırabilecek bir güvenli dizi <P1, …, Pn> vardır.
- Pi'nin kalan ihtiyacı ≤ boştakiler + Pj (j < i) tarafından tutulanlar.
- Güvensiz ≠ kilitlenmiş. Güvensiz durumda henüz kilitlenme yoktur; süreçler azami isteğini yapmazsa her şey yolunda gidebilir. Ama sistem artık bitişi garanti edemez.
- Kaçınma algoritması sistemi her zaman güvenli durumda tutar.
Kaçınma
Güvenli Durum Örneği
- Tek kaynak türü, 10 örnek.
- Has: şu an tutulan; Max: bitene kadar gerekecek en çok.
- Kalan ihtiyaç = Max − Has.
- İS her adımda isteklerin dizisini kendisi seçebilecek konumdadır.
(a) Toplam 10 örnek; 7'si dağıtılmış, 3 boş. Güvenli mi? Bir güvenli dizi arayalım.
(b) B'nin kalan ihtiyacı 2 ≤ 3: B'ye 2 verilir, B azamisine ulaşır.
(c) B biter ve 4 örneği bırakır: boş 5.
(d) C'nin kalan ihtiyacı 5 ≤ 5: C'ye 5 verilir.
(e) C biter: boş 7. A'nın kalan 6'sı karşılanır. B → C → A güvenli dizisi var: durum güvenli.
Tanenbaum MOS Şekil 6-9.
Kaçınma
Güvensiz Durum Örneği
- Fark tek bir karar: (a)'da A'ya fazladan bir örnek vermek.
- (b) henüz kilitlenme değildir. A, ek isteğini yapmadan bir kaynağı bırakırsa sorun çıkmayabilir.
- Ama İS en kötü durumu varsayar: herkes azami isteğini yaparsa bitiş garanti değil.
Aynı başlangıç (güvenli). Şimdi A bir örnek daha ister ve İS bunu verir.
(b) A: 4/9, boş 2. Güvenli dizi var mı?
(c) Yalnızca B bitebilir (ihtiyaç 2 ≤ 2): B'ye 2 verilir.
(d) B biter: boş 4. A'nın 5, C'nin 5 ihtiyacı var: hiçbiri garanti edilemez. (b) durumu güvensizdi; A'nın isteği ertelenmeliydi.
Tanenbaum MOS Şekil 6-10.
Kaçınma
Bankacı Algoritması: Tek Kaynak
- Her istekte: “Bu isteği verirsem durum güvenli kalır mı?”
- Evet → ver. Hayır → ertele (süreç bekler, istek sonra yeniden değerlendirilir).
- Güvenlik: kalan ihtiyacı boştakilerle karşılanabilen bir müşteri bul, bitmiş say, kredisini kasaya ekle; tekrarla.
(a) Bankacı (Dijkstra, 1965): kasada 10 birim, 4 müşterinin kredi limitleri toplamı 22. Herkes aynı anda azami istemez.
(b) Boş 2. C'nin ihtiyacı 2 ≤ 2 → C biter (boş 4), sonra D (3 ≤ 4 → boş 8), A, B. Güvenli.
(c) (b)'deyken B bir birim daha isterse: boş 1, en küçük ihtiyaç 2. Güvensiz → istek reddedilip B bekletilmelidir.
Kaçınma
Bankacı Algoritması: Çoklu Kaynak
Available[m]: her türden boş örnek.Max[n][m]: her sürecin önceden bildirdiği azami istek.Allocation[n][m]: şu an tutulan.Need = Max − Allocation: kalan ihtiyaç.
/* güvenlik algoritması */ Work ← Available Finish[i] ← false (tüm i) while Finish[i] = false ve Need[i] ≤ Work olan i var: Work ← Work + Allocation[i] Finish[i] ← true tüm i için Finish[i] ise GÜVENLİ
/* Ti, Request[i] isterse */ if Request[i] > Need[i]: hata /* Max aşıldı */ if Request[i] > Available: Ti bekler /* kaynak yok */ /* varmış gibi yap: */ Available -= Request[i] Allocation[i] += Request[i] Need[i] -= Request[i] if güvenli: isteği ver else: geri al, Ti bekler
Karmaşıklık: güvenlik testi O(m · n²); her istekte çalışır.
Kaçınma · Algoritmayı adım adım çalıştır
Güvenlik Algoritması: Örnek
Work ← Available Finish[i] ← false for i = T0 … T4 (tekrar tekrar): if Finish[i] = false and Need[i] ≤ Work: Work ← Work + Allocation[i] Finish[i] ← true if tüm Finish[i]: GÜVENLİ
A=10, B=5, C=7 örnek. Available = (3 3 2). Need = Max − Allocation hesaplandı.
T0: Need (7 4 3) ≤ (3 3 2)? Hayır, geç.
T1: (1 2 2) ≤ (3 3 2) ✓ → biter, Work = (3 3 2) + (2 0 0) = (5 3 2).
T2: (6 0 0) ≤ (5 3 2)? A yetmez ✗.
T3: (0 1 1) ✓ → Work = (7 4 3).
T4: (4 3 1) ✓ → Work = (7 4 5).
İkinci tur. T0: (7 4 3) ≤ (7 4 5) ✓ → Work = (7 5 5).
T2: (6 0 0) ✓ → Work = (10 5 7), yani tüm kaynaklar.
Tüm Finish true: durum güvenli. <T1, T3, T4, T2, T0> gibi başka güvenli diziler de vardır.
Silberschatz 10e §8.6.3.3 örneği. Max: T0 (7 5 3), T1 (3 2 2), T2 (9 0 2), T3 (2 2 2), T4 (4 3 3).
Kaçınma
İstek Kabul: T1 (1 0 2)
- Üç adım: Need kontrolü, Available kontrolü, güvenlik testi.
- Güvenlik testi “varmış gibi” durumda yapılır; durum güvensiz çıksaydı değişiklikler geri alınırdı.
- Hesaplar: Python betiğiyle doğrulandı.
T1, (1 0 2) ister. 1. kontrol: bildirdiği azami ihtiyacı aşmıyor ✓.
2. kontrol: kaynaklar şu an boşta ✓. Ama bu tek başına yetmez.
İsteği vermiş gibi yeni durumu hesapla.
Güvenlik algoritması yeni durumda <T1, T3, T4, T0, T2> dizisini bulur: güvenli → istek verilir.
Kaçınma
İstek Reddi: T4 (3 3 0) ve T0 (0 2 0)
- Bekleme nedeni 1: kaynak yok (T4).
- Bekleme nedeni 2: kaynak var ama vermek durumu güvensiz yapar (T0).
- Kaçınmanın bedeli budur: kaynaklar bazen boşta beklerken istek ertelenir; kullanım oranı düşer.
T1'in isteği verildikten sonra T4, (3 3 0) ister. Need'i aşmıyor ama A türünden yalnızca 2 boş: T4 bekler.
T0, (0 2 0) ister. İki kontrol de geçer; kaynak fiilen boşta.
Varmış gibi: Available = (2 1 0). Hangi Need ≤ (2 1 0)? T1 (0 2 0): B yetmez; T3 (0 1 1): C yetmez…
Hiçbir süreç bitirilemiyor: durum güvensiz. Değişiklikler geri alınır, T0 bekletilir; kaynak boşta olduğu hâlde.
Kaçınma
Çoklu Kaynak: İkinci Örnek
Beş süreç, dört kaynak türü (Tp, Pl, Yz=yazıcı, CD). A = E − P = (1 0 2 0).
D (0 0 1 0) ≤ A → biter, A = (2 1 2 1); E, A, B, C de sırayla biter. Durum güvenli.
B bir yazıcı ister. Verilirse A = (1 0 1 0); D yine bitebilir ve dizi korunur: verilir.
Ardından E son yazıcıyı isterse A = (1 0 0 0) olur ve hiçbir satır karşılanamaz: güvensiz → ertelenir.
Tanenbaum MOS Şekil 6-12. Eski sunumdaki “her satırda ≤ A olan satırı ara” adımları burada güvenlik testidir; aynı mantık tespit algoritmasında istek matrisiyle, kaçınmada kalan ihtiyaç matrisiyle kullanılır.
Kaçınma
Bankacı Algoritması Pratikte
Her süreç azami ihtiyacını önceden bildirir; süreç sayısı sabittir; kaynak sayısı değişmez (aygıt bozulmaz); süreçler kaynakları sonlu sürede bırakır.
Bu varsayımlar genel amaçlı İS'lerde tutmaz; algoritma neredeyse hiç kullanılmaz. Benzer “kabul denetimi” fikri: gerçek zamanlı zamanlama, bulut kotaları, havuzlu bağlantı limitleri.
- Eski sunumda kaçınma “tespit ya da kurtarmadan daha verimli” olarak anılıyordu: her istekte O(m·n²) test ve gereksiz ertelemeler nedeniyle genellikle daha pahalıdır; avantajı kurtarma gerektirmemesidir.
- “Algoritma arka planda sürekli çalışır” ifadesi de yanlıştı: test yalnızca bir istek geldiğinde (ve bir kaynak bırakıldığında bekleyenler için) yapılır.
Önleme
Önleme: Koşullara Saldırmak
| Koşul | Saldırı | Bedeli |
|---|---|---|
| Karşılıklı dışlama | Kaynağı paylaşılabilir yap: biriktirme (spooling), salt okunur paylaşım, kilitsiz yapılar | Çoğu kaynak doğası gereği paylaşılamaz (mutex!) |
| Tut ve bekle | Tüm kaynakları başta tek seferde iste; ya da yeni istekten önce elindekileri bırak | Düşük kullanım, açlık; ihtiyaç önceden bilinmeli |
| Kesme yok | Bekleyecek sürecin kaynaklarını geri al; tryLock + geri çekil; sanallaştır | Yalnızca durumu kaydedilebilen kaynaklarda; canlı kilit riski |
| Döngüsel bekleme | Kaynaklara toplam sıra ver, yalnızca artan sırada iste (kilit sıralaması) | Sıraya uymak programcı disiplini ister |
Önleme
Karşılıklı Dışlamaya Saldırı
- Biriktirme (spooling): süreçler çıktıyı diske yazar; yazıcıyı tek bir daemon sırayla kullanır. Yazıcı için çekişme kalkar.
- Salt okunur dosyalar ve kod sayfaları aynı anda paylaşılır; okur kilitleri birbirini dışlamaz.
- Kilitsiz (lock-free) yapılar CAS ile ilerler; kilit olmadığı için kilitlenme de olmaz (açlık hâlâ mümkün).
- Sınır: biriktirme diski de bir kaynaktır. Disk, yarım kalmış çıktılarla dolarsa yine kilitlenme olabilir (Tanenbaum).
- Genel ilke: bir kaynağı gerçekten gerekmedikçe atama, onu isteyecek süreç sayısını en aza indir.
Önleme
Tut ve Beklemeye Saldırı
- Protokol 1: süreç ihtiyaç duyacağı tüm kaynakları çalışmaya başlamadan önce tek bir istekte alır (hepsi ya da hiçbiri).
- Protokol 2: süreç yalnızca elinde hiçbir kaynak yokken istek yapabilir: yenisini istemeden önce tuttuklarını bırakır.
- Örnek: DVD → disk kopyala, diski sırala, yazıcıya bas. Protokol 1'de yazıcı en baştan sona kadar boşa tutulur.
- Sorunlar: düşük kaynak kullanımı; çok kaynak isteyen süreç için açlık; ihtiyaçlar çoğu zaman önceden bilinmez.
- Pratikte:
pthread_mutex_trylockile “ya hepsi ya hiçbiri” edinimi; veritabanlarında tüm kilitleri baştan alan muhafazakâr 2PL.
Silberschatz 10e §8.5.2.
Önleme
Kesme Yok Koşuluna Saldırı
- Geri alma protokolü: kaynak tutan bir süreç hemen karşılanamayan bir istek yaparsa, tuttuğu tüm kaynaklar örtük olarak bırakılır; süreç hepsini birlikte alabildiğinde yeniden başlar.
- Yalnızca durumu kaydedilip geri yüklenebilen kaynaklara uygundur: CPU yazmaçları, bellek, veritabanı işlemi (abort).
- Sanallaştırma: yazıcı biriktirilir, bellek sayfalanır.
- Mutex için: zaman aşımlı deneme. Edinemeyen iş parçacığı elindekini kendisi bırakır ve rastgele bir süre sonra yeniden dener.
- Çalıştırıldı (JDK 21): 2 iş parçacığı × 1000 ters yönlü transfer, sonuç
x=1000 y=1000 toplam=2000.
boolean dene(Hesap k, Hesap h, int m) throws InterruptedException { if (!k.kilit.tryLock(50, MILLISECONDS)) return false; try { if (!h.kilit.tryLock(50, MILLISECONDS)) return false; /* k'yi de bırak */ try { k.bakiye -= m; h.bakiye += m; return true; } finally { h.kilit.unlock(); } } finally { k.kilit.unlock(); } } /* çağıran: while (!dene(x, y, 1)) Thread.sleep(rastgele); */
Rastgele bekleme önemli: iki iş parçacığı aynı ritimde dener-bırakırsa canlı kilit oluşur (ileride).
Önleme
Döngüsel Beklemeye Saldırı
| # | Kaynak |
|---|---|
| 1 | Görüntüleyici |
| 2 | Yazıcı |
| 3 | Çizici |
| 4 | Teyp sürücü |
| 5 | Blu-ray sürücü |
Yazıcı ve teyp gerekiyorsa önce 2, sonra 4 istenir. Uygun bir sıralamayı bulmak en zor kısımdır.
Her kaynak türüne bir numara verilir. Kural: süreç yalnızca elindekilerden büyük numaralı kaynak isteyebilir.
A, i'yi tutup j'yi istiyorsa kurala göre i < j.
B, j'yi tutup i'yi isterse j < i olmalı: çelişki. Bu kenar hiç oluşamaz. Genel olarak döngüdeki en büyük numaralı kaynağı tutan süreç daha büyüğünü isteyemez.
Tanenbaum MOS Şekil 6-13. Varyant: süreç Kj'yi isteyecekse elindeki tüm Ki (i ≥ j) kaynaklarını önce bırakmalıdır.
Önleme · Kodu adım adım çalıştır
Kilit Sıralaması Pratikte
void transfer(Hesap k, Hesap h, int m) { Hesap ilk = k.id < h.id ? k : h; Hesap ikinci = k.id < h.id ? h : k; ilk.kilit.lock(); try { ikinci.kilit.lock(); try { k.bakiye -= m; h.bakiye += m; } finally { ikinci.kilit.unlock(); } } finally { ilk.kilit.unlock(); } } /* T1: transfer(x, y, 1) x.id = 1 T2: transfer(y, x, 1) y.id = 2 */
T1 x→y, T2 y→x aktarıyor: “doğal” sıra iki iş parçacığında terstir. Kilitlerin id sırası ise ortaktır.
T1: ilk = x (1 < 2). x kilidini alır.
T2: k = y ama ilk yine x (id 1). x'i bekler; elinde hiçbir kilit yok.
T1 y'yi de alır (kimse tutmuyor) ve aktarımı yapar.
T1 kilitleri bırakır; T2 x'i, sonra y'yi alır. Döngü oluşamaz.
Çalıştırıldı (JDK 21): her biri 100 000 ters yönlü aktarım, sonuç x=1000 y=1000, kilitlenme yok.
Linux çekirdeği aynı türden iki kilidi adres sırasıyla alır (ör. double_rq_lock); kilit sırası belgelenir ve lockdep ile denetlenir.
Diğer Sorunlar
İki Aşamalı Kilitleme (2PL)
- Veritabanı işlemleri için protokol: büyüme evresinde yalnızca kilit alınır, küçülme evresinde yalnızca bırakılır; ilk bırakıştan sonra yeni kilit alınamaz.
- Amacı serileştirilebilirliktir (işlemler sanki sırayla çalışmış gibi), kilitlenmeyi önlemek değil. Düz 2PL kilitlenebilir: T1 a'yı, T2 b'yi kilitler; sonra çapraz isterler.
- Tanenbaum'un varyantı: 1. evrede tüm kayıtları kilitlemeyi dene; biri kilitliyse hepsini bırak ve baştan başla. Bu, tut ve beklemeyi kaldırır.
- Katı (strict) 2PL: kilitler işlem sonunda (commit/abort) bırakılır. Kilitlenmeleri DBMS bekleme çizgesiyle tespit edip bir işlemi geri sarar.
Diğer Sorunlar
İletişim Kilitlenmeleri
- İletişim kilitlenmesi: kaynak yoktur, süreçler birbirinden mesaj bekler. A, B'ye istek gönderip yanıt bekler; istek kaybolursa A yanıtı, B isteği sonsuza dek bekler.
- Kaynak sıralaması ya da kaçınma işe yaramaz; çözüm zaman aşımı (timeout) ve yeniden gönderme. Yinelenen mesajlar için protokolde sıra numarası gerekir.
- Ağ donanımında ise tamponlar gerçek kaynaktır; aşağıdaki halka bir kaynak kilitlenmesidir.
Dört yönlendirici halka biçiminde; her birinin sınırlı tampon belleği var.
Yoğun trafikte tüm tamponlar, saat yönünde bir sonraki yönlendiriciye gidecek paketlerle dolar.
A, B'nin boş tamponunu bekler; B, C'nin; C, D'nin; D, A'nın: döngüsel bekleme. Çözüm: zaman aşımıyla paket düşürme, sanal kanallar, kredi tabanlı akış denetimi.
Tanenbaum MOS §6.7.2, Şekil 6-15.
Diğer Sorunlar
Canlı Kilit (Livelock)
- Koridorda karşılaşan iki kişi aynı anda aynı yana kayar: kimse geçemez.
- Kilitlenmede süreçler uyur; canlı kilitte çalışır ama faydalı iş yapmaz.
void process_A(void) { enter_region(&resource_1); enter_region(&resource_2); use_both_resources(); leave_region(&resource_2); leave_region(&resource_1); } /* B: önce resource_2, sonra 1 */
Tanenbaum Şekil 6-16: meşgul beklemeli enter_region ters sırada çağrılırsa süreçler bloke olmadan sonsuza dek döner.
A r1'i, B r2'yi alır. A r2'yi dener (tryLock başarısız), B r1'i dener (başarısız).
Kibar davranırlar: ikisi de elindekini bırakır ve aynı süre sonra yeniden dener. Aynı şey tekrarlanır.
Süreçler bloke değil, CPU harcıyor, durumları sürekli değişiyor; ama hiçbiri ilerlemiyor: canlı kilit.
Çözüm: rastgele (üstel) geri çekilme, öncelik/sıra numarası ya da kilit sıralaması. Ethernet'in CSMA/CD geri çekilmesi aynı fikirdir.
Diğer Sorunlar
Açlık (Starvation)
- Bir süreç, kaynak kullanılabilir olduğu hâlde ona hiç sıra gelmediği için süresiz bekler. Diğerleri ilerler: sistem kilitlenmemiştir.
- Kaynak dağıtım politikasının sonucudur. Örnek: yazıcıyı her seferinde en küçük dosyaya vermek ortalama bekleme süresini azaltır ama büyük dosyayı aç bırakabilir.
- Başka örnekler: katı öncelikli zamanlama, okur öncelikli okur-yazar kilidi, kurtarmada hep aynı kurbanın seçilmesi.
- Çözüm: ilk gelen ilk hizmet alır (FIFO) ya da bekledikçe önceliği artırma (yaşlandırma).
| Kilitlenme | Canlı kilit | Açlık | |
|---|---|---|---|
| Süreç durumu | bloke | çalışıyor | hazır/bloke |
| Kim etkilenir? | döngüdeki herkes | etkileşen grup | bir ya da birkaç süreç |
Pratikte Kilitlenme · Kodu adım adım çalıştır
Java'da Kilitlenme
Object a = new Object(), b = new Object(); Thread t1 = new Thread(() -> { synchronized (a) { uyu(10); /* pencereyi büyüt */ synchronized (b) { isle(); } } }, "T1"); Thread t2 = new Thread(() -> { synchronized (b) { uyu(10); synchronized (a) { isle(); } } }, "T2"); t1.start(); t2.start();
İki iş parçacığı iki monitörü (synchronized kilidi) ters sırada alacak.
T1 a'nın monitörüne girer ve uyur.
Bu sırada T2 b'nin monitörüne girer.
T1 uyanır, b'yi ister: b T2'de → T1 BLOCKED.
T2 a'yı ister → BLOCKED. JVM monitörleri kesilemez: program asla bitmez.
uyu(10) zamanlamayı çok olası kılar ama garanti etmez. CountDownLatch ile iki ilk kilit alınana dek bekletilen sürüm JDK 21'de her çalıştırmada kilitlendi.
Pratikte Kilitlenme
Kilitlenmeyi Bulmak: jstack
$ jstack <pid>
Found one Java-level deadlock:
=============================
"T1":
waiting to lock monitor 0x… (object 0x…, a java.lang.Object),
which is held by "T2"
"T2":
waiting to lock monitor 0x… (object 0x…, a java.lang.Object),
which is held by "T1"
Java stack information for the threads listed above:
"T1":
at Asili.calis(Asili.java:7)
- waiting to lock <0x…d0> (a java.lang.Object)
- locked <0x…c0> (a java.lang.Object)
…
Found 1 deadlock.JDK 21'de gerçek çıktı (adresler kısaltıldı). Aynı rapor: jcmd <pid> Thread.print, JConsole/VisualVM “Detect Deadlock”.
ThreadMXBean mx = ManagementFactory.getThreadMXBean(); long[] ids = mx.findDeadlockedThreads(); if (ids != null) for (ThreadInfo ti : mx.getThreadInfo(ids)) System.out.println(ti.getThreadName() + " bekliyor, kilit sahibi " + ti.getLockOwnerName());
T1 bekliyor, kilit sahibi T2 T2 bekliyor, kilit sahibi T1
- JVM, monitör ve
ReentrantLocksahipliğinden bekleme çizgesi kurup döngü arar. - Tespit eder ama kurtarmaz: süreci yeniden başlatmak gerekir.
Pratikte Kilitlenme
Araçlar: lockdep ve Diğerleri
| Ortam | Araç / davranış |
|---|---|
| Linux çekirdeği | lockdep (CONFIG_PROVE_LOCKING): kilit sırası doğrulayıcı; hung task dedektörü |
| C/C++ | ThreadSanitizer: lock-order-inversion; Valgrind Helgrind |
| Java | jstack, jcmd, ThreadMXBean |
| Go | fatal error: all goroutines are asleep - deadlock! |
| Veritabanı | PostgreSQL, InnoDB: bekleme çizgesi + kurban işlemi geri sarma |
lockdep her kilidi bir sınıfa (aynı türdeki tüm örnekler) bağlar.
Bir görev A'yı tutarken B'yi alınca “A → B” kenarı kaydedilir.
Başka bir yolda B tutulurken A alınırsa çizgede döngü oluşur: kilitlenme hiç yaşanmadan rapor edilir.
lockdep ve TSan potansiyel kilitlenmeyi bulur (sıra ihlali); jstack ve Go çalışma zamanı ise gerçekleşmiş kilitlenmeyi raporlar.
Özet
Özet
| Yaklaşım | Ne zaman? | Bilgi gereksinimi | Bedel | Kullanım |
|---|---|---|---|---|
| Görmezden gel | — | yok | ara sıra yeniden başlatma | genel amaçlı İS |
| Tespit + kurtarma | sonra | şu anki tahsis ve istekler | periyodik O(m·n²), kayıp iş | veritabanları, JVM araçları |
| Kaçınma | her istekte | azami ihtiyaçlar (Max) | ertelemeler, O(m·n²)/istek | nadiren, özel sistemler |
| Önleme | tasarımda | kaynak sırası | esneklik ve kullanım kaybı | çekirdek, uygulama kodu |
- Dört koşul birlikte gereklidir; tek örnekli kaynaklarda döngü ⇔ kilitlenme.
- Güvensiz durum kilitlenme değildir ama bitiş garantisi yoktur.
- Pratikte en etkili araç: kilit sıralaması + zaman aşımlı deneme + araçlarla (lockdep, jstack, TSan) denetim.
Özet
Kontrol Soruları
- Kilitlenmenin dört koşulunu yazın. Hangisi bir politika değil, durumdur?
- Çizgede döngü varken kilitlenme olmaması nasıl mümkündür? Örnek verin.
- E = (4 2 3 1), A = (2 1 0 0) örneğinde P3'ün isteği (2 1 0 1) olsaydı sonuç ne olurdu?
- Güvensiz durum ile kilitlenmiş durum arasındaki fark nedir?
- Silberschatz örneğinde T1'in (1 0 2) isteğinden sonra T0 (0 2 0) isterse ne olur? Neden?
- Bankacı algoritması genel amaçlı İS'lerde neden kullanılmaz?
- Kaynak numaralandırma döngüsel beklemeyi neden imkânsız kılar?
- Canlı kilit ile kilitlenme arasındaki fark nedir? Canlı kilit nasıl kırılır?
Cevaplar
- Karşılıklı dışlama, tut ve bekle, kesme yok, döngüsel bekleme; döngüsel bekleme o anki durumdur.
- Çok örnekli kaynakta döngü dışındaki bir süreç örneğini bırakabilir (Silberschatz Şekil 8.6: T4, R2'yi bırakır).
- Hiçbir satır ≤ A olmaz; P1, P2, P3 kilitlenmiştir.
- Güvensizde henüz kimse kalıcı olarak bloke değildir ama herkesin bitmesi garanti edilemez; kilitlenmede döngü oluşmuştur.
- Kaynak boşta olsa da varmış gibi durumda Available = (2 1 0) ve hiçbir Need karşılanamaz: güvensiz, T0 bekletilir.
- Azami ihtiyaçlar önceden bilinmez, süreç ve kaynak sayısı değişir, her istekteki test pahalıdır.
- Döngüdeki en büyük numaralı kaynağı tutan süreç daha küçük numaralı bir kaynak isteyemez; döngü kapanamaz.
- Kilitlenmede süreçler bloke, canlı kilitte çalışıyor ama ilerlemiyor; rastgele geri çekilme ya da sıralama ile kırılır.
Özet
Kaynaklar
- A. Silberschatz, P. B. Galvin, G. Gagne, Operating System Concepts, 10. baskı, Wiley, 2018 — Bölüm 8: Deadlocks.
- A. S. Tanenbaum, H. Bos, Modern Operating Systems, 4. baskı (2014) / 5. baskı (2022), Pearson — Bölüm 6: Deadlocks.
- R. H. Arpaci-Dusseau, A. C. Arpaci-Dusseau, Operating Systems: Three Easy Pieces (OSTEP), ostep.org — “Common Concurrency Problems”.
- E. G. Coffman, M. J. Elphick, A. Shoshani, “System Deadlocks”, ACM Computing Surveys 3(2), 1971.
- E. W. Dijkstra, “Cooperating Sequential Processes”, EWD-123, 1965 (Bankacı algoritması); R. C. Holt, “Some Deadlock Properties of Computer Systems”, ACM Computing Surveys, 1972.
- Linux çekirdek belgeleri:
Documentation/locking/lockdep-design.rst. - Java SE 21:
java.lang.management.ThreadMXBean,java.util.concurrent.locks.ReentrantLock;jstackkılavuzu. - PostgreSQL belgeleri: “Explicit Locking — Deadlocks”,
deadlock_timeout.