Bölüm 4: İş Parçacıkları
Giriş
Nasıl çalışalım?
30 soru · Çoktan seçmeli: 16 · Açık uçlu: 7 · Doğru / Yanlış: 2 · Hesaplama: 3 · Kod izleme: 2. Sorular konu başlıklarına göre gruplanmış ve kolaydan zora sıralanmıştır.
Soru 1 · Temel Kavramlar
Hangisi Paylaşılmaz?
Çoktan seçmeli Aynı süreçteki iki iş parçacığı düşünün. Aşağıdakilerden hangisi bu iki iş parçacığı arasında paylaşılmaz, her birine özeldir?
- Global değişkenler
- Öbekte
mallocile ayrılan veri - Yığın, program sayacı ve yazmaçlar
- Açık dosya tanımlayıcıları
- Programın kod bölümü
Cevabı göster
Doğru cevap: C · Yığın, program sayacı ve yazmaçlar
Adres uzayı (kod, veri, öbek) ve dosyalar, sinyal işleyicileri gibi kaynaklar sürecindir ve tüm iş parçacıklarınca paylaşılır. Her iş parçacığının ise kendi yürütme durumu vardır: PC, yazmaçlar, yığın; bunlar TCB’de tutulur.
Soru 2 · Temel Kavramlar
Süreç ile İş Parçacığı
Çoktan seçmeli Aşağıdaki ifadelerden hangisi süreç ile iş parçacığı arasındaki farkı en doğru anlatır?
- Süreç kaynakların (adres uzayı, açık dosyalar) sahibidir; iş parçacığı bu kaynakları paylaşan, kendi PC’si ve yığını olan bir yürütme akışıdır
- İş parçacığı birden fazla sürece aynı anda ait olabilir
- Süreçler yalnızca tek çekirdekte çalışabilir; iş parçacıkları ise çok çekirdekte
- İş parçacıkları çekirdek tarafından hiçbir zaman görülmez
Cevabı göster
Doğru cevap: A · Süreç kaynakların (adres uzayı, açık dosyalar) sahibidir; iş parçacığı bu kaynakları paylaşan, kendi PC’si ve yığını olan bir yürütme akışıdır
Tanenbaum’un ifadesiyle süreç kaynakları gruplar, iş parçacığı yürütülür. Bir iş parçacığı tek bir sürece aittir. Linux ve Windows’ta iş parçacıkları çekirdek tarafından tanınır ve ayrı ayrı çizelgelenir; yalnızca kullanıcı düzeyi kütüphanelerde çekirdek onları görmez.
Soru 3 · Temel Kavramlar
Sekmeler: Süreç mi, İş Parçacığı mı?
Açık uçlu Bir tarayıcı ekibi her sekmeyi ayrı bir süreç mi yoksa aynı süreçte ayrı bir iş parçacığı mı yapmalı? Kararınızı adres uzayı, kaynak paylaşımı ve iletişim, oluşturma/geçiş maliyeti ve hata yalıtımı açısından gerekçelendirin.
Cevabı göster
| Ayrı süreç | Ayrı iş parçacığı | |
|---|---|---|
| Adres uzayı | Her sekmenin kendi adres uzayı | Tüm sekmeler aynı adres uzayında |
| Paylaşım, iletişim | IPC gerekir, daha yavaş | Ortak bellekten doğrudan, ama eşzamanlama şart |
| Maliyet | Oluşturma ve geçiş pahalı, bellek fazla | Hafif: oluşturma ve geçiş ucuz |
| Hata yalıtımı | Çöken sekme yalnız kendini kapatır; kum havuzu mümkün | Bir iş parçacığı çökerse tüm tarayıcı çöker |
Güvenlik ve kararlılık öncelikliyse süreç (Chrome bu yolu seçti); sekme içinde ise işleme, ağ ve arayüz için iş parçacıkları kullanılır.
Soru 4 · Temel Kavramlar
İş Parçacıkları Hakkında
Doğru / Yanlış İfadeleri değerlendirin.
- Bir iş parçacığı geçersiz bir göstericiye yazıp çökerse yalnızca o iş parçacığı sonlanır.
- Aynı süreçteki iki iş parçacığı arasında geçiş, iki süreç arasında geçişten genellikle daha ucuzdur.
- POSIX’e göre bir sürecin tüm iş parçacıkları
getpid()ile aynı değeri görür.
Cevabı göster
- Yanlış. Bellek hatası sinyali (
SIGSEGV) tüm süreci sonlandırır; iş parçacıkları arasında yalıtım yoktur. - Doğru. Adres uzayı değişmediği için sayfa tablosu değiştirilmez, TLB ve önbellek içeriği büyük ölçüde geçerli kalır.
- Doğru. PID sürece aittir; her iş parçacığının ayrıca kendi kimliği vardır (
pthread_self, Linux’tagettid).
Soru 5 · Temel Kavramlar
Çok İş Parçacığından Ne Beklenmez?
Çoktan seçmeli Aşağıdakilerden hangisi çok iş parçacıklı programlamanın bir yararı değildir?
- Yanıt verebilirlik: uzun bir iş sürerken arayüz donmaz
- Kaynak paylaşımı: veriler aynı adres uzayında doğrudan paylaşılır
- Ekonomi: oluşturma ve geçiş süreçlere göre ucuzdur
- Hata yalıtımı: bir iş parçacığının hatası diğerlerini etkilemez
- Ölçeklenebilirlik: çok çekirdekte paralel çalışma
Cevabı göster
Doğru cevap: D · Hata yalıtımı: bir iş parçacığının hatası diğerlerini etkilemez
Ortak adres uzayı, paylaşımın kolaylığının bedelidir: bir iş parçacığı diğerlerinin verisini bozabilir ya da tüm süreci çökertebilir. Yalıtım istendiğinde süreçler kullanılır.
Soru 6 · Temel Kavramlar
Üç İş Parçacıklı Kelime İşlemci
Açık uçlu Bir kelime işlemcide klavyeyi dinleyen, metni yeniden biçimlendiren ve belgeyi arka planda kaydeden üç ayrı iş parçacığı var. Program tek iş parçacıklı olsaydı kullanıcı ne yaşardı? Çok iş parçacıklı tasarımın getirdiği iki risk nedir?
Cevabı göster
Tek iş parçacığında, 600 sayfalık belgeyi yeniden biçimlendirirken ya da diske kaydederken program tuş basışlarına yanıt veremez; arayüz donar. Üç ayrı süreç de çözüm olmaz, çünkü üçü aynı belge verisine erişmelidir.
- Yarış koşulu: kaydetme iş parçacığı, biçimlendirme metni değiştirirken tutarsız bir ara durumu diske yazabilir → kilit gerekir.
- Kilitlenme ve hata ayıklama zorluğu: yanlış kilit sırası iş parçacıklarını sonsuza dek bekletebilir; hatalar zamanlamaya bağlı olduğu için yeniden üretmek zordur.
Soru 7 · Temel Kavramlar
İş Parçacığı Olmadan Eşzamanlı Sunucu
Açık uçlu Binlerce istemciye hizmet veren bir sunucu tek iş parçacığıyla nasıl eşzamanlı çalışabilir? Bu olay güdümlü tasarımın bir artısını ve bir eksisini yazın.
Cevabı göster
Olay döngüsü: tüm soketler engellemeyen (non-blocking) kipe alınır; döngü select/poll/epoll ile hazır olan bağlantıları bekler ve her olayı kısa bir işleyiciyle ele alır (bir sonlu durum makinesi gibi).
- Artı: iş parçacığı oluşturma, bağlam değiştirme ve kilit yok; aynı anda tek işleyici çalıştığından yarış koşulu yok, bellek kullanımı düşük.
- Eksi: bloke eden tek bir çağrı (ör. disk okuma, uzun hesap) tüm sunucuyu durdurur; çok çekirdekten yararlanmak için birden çok döngü gerekir; kod geri çağırmalara bölündüğü için karmaşıklaşır.
Soru 8 · Eşzamanlılık ve Paralellik
Tek Çekirdekte Dört İş Parçacığı
Çoktan seçmeli Tek çekirdekli bir makinede dört iş parçacığı zaman paylaşımıyla sırayla çalışıyor. Bu durum için hangisi doğrudur?
- Paraleldir ama eşzamanlı değildir
- Eşzamanlıdır ama paralel değildir
- Hem eşzamanlı hem paraleldir
- Ne eşzamanlı ne paraleldir
Cevabı göster
Doğru cevap: B · Eşzamanlıdır ama paralel değildir
Dördü de aynı zaman aralığında ilerler (eşzamanlılık), ama herhangi bir anda yalnızca biri çalışır. Paralellik için birden çok çekirdek ya da işlemci gerekir.
Soru 9 · Eşzamanlılık ve Paralellik
Eşzamanlılık ile Paralellik
Açık uçlu Bir aşçı iki tencereyi sırayla karıştırarak iki yemeği birlikte pişiriyor; başka bir mutfakta iki aşçı iki yemeği aynı anda pişiriyor. Bu benzetmeyi kullanarak eşzamanlılık ve paralellik kavramlarını tanımlayın ve farklarını açıklayın.
Cevabı göster
- Eşzamanlılık (concurrency): birden çok işin aynı zaman diliminde ilerlemesidir; işler iç içe geçirilerek yürütülür. Tek aşçı = tek çekirdekte zaman paylaşımı.
- Paralellik (parallelism): birden çok işin fiziksel olarak aynı anda yürütülmesidir. İki aşçı = iki çekirdek.
Eşzamanlılık programın yapısıyla (birbirinden bağımsız ilerleyebilen görevler), paralellik donanımın olanağıyla ilgilidir. Paralellik eşzamanlılığı gerektirir; tersi doğru değildir.
Soru 10 · Eşzamanlılık ve Paralellik
Hangi Tür Paralellik?
Çoktan seçmeli On milyon elemanlı bir dizinin toplamı, dizi dört eşit parçaya bölünüp her parça ayrı bir çekirdekte toplanarak hesaplanıyor. Bu hangi tür paralelliktir?
- Görev paralelliği
- Veri paralelliği
- Boru hattı paralelliği
- Hiçbiri; yalnızca eşzamanlılıktır
Cevabı göster
Doğru cevap: B · Veri paralelliği
Aynı işlem verinin farklı parçalarına uygulanıyor: veri paralelliği. Görev paralelliğinde ise farklı işler (ör. biri toplam, biri en büyük değer) farklı çekirdeklerde çalışır.
Soru 11 · Eşzamanlılık ve Paralellik
Amdahl Yasası: Kaç Kat Hızlanır?
Hesaplama Bir görüntü işleme programının çalışma süresinin %10’u paralelleştirilemiyor (S = 0,1). Amdahl yasasına göre 8 ve 16 çekirdekte hızlanma nedir? Çekirdek sayısı sonsuza giderse üst sınır nedir? 16 çekirdekte verim (hızlanma / çekirdek) ne olur?
Cevabı göster
Hızlanma ≤ 1 / (S + (1 − S) / N)
- N = 8: 1 / (0,1 + 0,1125) = 1 / 0,2125 ≈ 4,71×
- N = 16: 1 / (0,1 + 0,05625) = 1 / 0,15625 = 6,40×
- N → ∞: 1 / 0,1 = 10×
16 çekirdekte verim 6,4 / 16 = %40: çekirdekleri ikiye katlamak hızlanmayı ancak 1,36 kat artırdı. Seri kısım küçük görünse de ölçeklenmeyi sınırlar.
Soru 11 · Adım Adım Çözüm
Soru 11: Adım Adım Çözüm
1. Paralel kısım 1 − S = 0,9; N çekirdekte süresi 0,9 / N’ye iner, seri kısım 0,1 aynı kalır.
2. N = 8: 0,1 + 0,9 / 8 = 0,2125 → 1 / 0,2125 ≈ 4,71×. N = 16: 0,1 + 0,05625 = 0,15625 → 6,40×.
3. N → ∞: paralel terim sıfıra gider, süre 0,1’de kalır → en fazla 10×; verim 16 çekirdekte %40.
Soru 12 · Eşzamanlılık ve Paralellik
Hedef Hızlanma İçin Seri Kısım
Hesaplama 8 çekirdekli bir sunucuda bir hesaplamanın en az 4 kat hızlanması isteniyor. Amdahl yasasına göre programın seri (paralelleştirilemeyen) kısmı en fazla yüzde kaç olabilir?
Cevabı göster
4 = 1 / (S + (1 − S) / 8) ⇒ S + (1 − S) / 8 = 0,25 ⇒ 8S + 1 − S = 2 ⇒ 7S = 1 ⇒ S = 1/7 ≈ 0,143.
Seri kısım en fazla yaklaşık %14,3 olabilir; yani kodun en az %85,7’si paralelleştirilmelidir. Kontrol: 1 / (0,1429 + 0,8571 / 8) = 1 / 0,25 = 4.
Soru 13 · İş Parçacığı Modelleri
Çekirdek Düzeyi İş Parçacığının Farkı
Çoktan seçmeli Bir iş parçacığı kütüphanesi ya tamamen kullanıcı alanında gerçeklenebilir ya da çekirdeğin desteğine dayanabilir. Çekirdeğin desteklediği (çekirdek düzeyi) iş parçacıklarının belirleyici özelliği hangisidir?
- Kullanıcı kipinde hiç çalışmazlar
- Hiçbir zaman bloke olmazlar
- Kendi yığınları yoktur
- Çekirdek her birini tanır ve ayrı ayrı çizelgeler; biri bloke olunca diğerleri çalışabilir
Cevabı göster
Doğru cevap: D · Çekirdek her birini tanır ve ayrı ayrı çizelgeler; biri bloke olunca diğerleri çalışabilir
Kullanıcı düzeyi iş parçacıklarını bir kütüphane yönetir: geçişleri çok hızlıdır (çekirdeğe girilmez) ama çekirdek yalnızca tek bir süreç görür. Çekirdek düzeyindekilerin oluşturma ve geçişi sistem çağrısı gerektirir, buna karşılık çok çekirdekte paralel çalışabilirler.
Soru 14 · İş Parçacığı Modelleri
Çoktan Bire Modelde read()
Çoktan seçmeli Çoktan bire (N:1) modelde, bir sürecin 8 kullanıcı düzeyi iş parçacığından biri bloke eden bir read() sistem çağrısı yaptı. Ne olur?
- Tek çekirdek iş parçacığı bloke olduğu için sürecin tüm iş parçacıkları bekler
- Yalnızca o iş parçacığı bekler, diğer yedisi çalışmayı sürdürür
- Çekirdek diğer iş parçacıklarını otomatik olarak başka çekirdeklere dağıtır
- Süreç hemen zombi olur
Cevabı göster
Doğru cevap: A · Tek çekirdek iş parçacığı bloke olduğu için sürecin tüm iş parçacıkları bekler
Çekirdek açısından süreçte tek bir çizelgelenebilir varlık vardır; o bloke olunca kütüphane başka bir iş parçacığına geçemez. Aynı nedenle N:1 modeli çok çekirdekten yararlanamaz. 1:1 modelinde yalnızca çağrıyı yapan iş parçacığı beklerdi.
Soru 15 · İş Parçacığı Modelleri
N:1, 1:1 ve M:N Modelleri
Açık uçlu Üç eşleme modelini paralellik, bloke eden çağrı davranışı ve maliyet açısından karşılaştırın. Günümüzde Linux ve Windows hangisini kullanır?
Cevabı göster
| N:1 | 1:1 | M:N | |
|---|---|---|---|
| Paralellik | Yok | Var | Var (en çok N çekirdek iş parçacığı kadar) |
| Bloke çağrı | Tüm süreç bekler | Yalnızca çağıran bekler | Yalnızca çağıran; çalışma zamanı diğerlerini başka çekirdek iş parçacığına taşır |
| Maliyet | En ucuz geçiş | Her iş parçacığı bir çekirdek nesnesi | Ucuz, ama gerçeklemesi karmaşık |
Linux (NPTL) ve Windows 1:1 kullanır. M:N fikri bugün dil çalışma zamanlarında yaşar: Go’nun goroutine’leri ve Java 21 sanal iş parçacıkları.
Soru 16 · İş Parçacığı Modelleri
Kullanıcı ve Çekirdek İş Parçacıkları
Doğru / Yanlış İfadeleri değerlendirin.
- Kullanıcı düzeyi iş parçacıkları arasında geçiş için çekirdek kipine girmek gerekmez.
- 1:1 modelinde oluşturulabilecek iş parçacığı sayısı çekirdek kaynaklarıyla sınırlıdır.
- Java 21’in sanal iş parçacıkları her biri bir çekirdek iş parçacığına kalıcı olarak bağlı olan 1:1 iş parçacıklarıdır.
Cevabı göster
- Doğru. Geçiş, kütüphanenin yazmaçları kaydedip yüklemesinden ibarettir; bu yüzden çok hızlıdır.
- Doğru. Her iş parçacığı bir çekirdek yığını ve çekirdek veri yapısı tüketir; on binlerce iş parçacığı pahalıdır. M:N modelinin çıkış noktası budur.
- Yanlış. Sanal iş parçacıkları az sayıda taşıyıcı (platform) iş parçacığı üzerinde çoğullanır: bu bir M:N modelidir; bloke olan sanal iş parçacığı taşıyıcısından ayrılır.
Soru 17 · Pthreads
İki İş Parçacığıyla Toplam
Kod izleme Program ne yazdırır? İkinci for döngüsü (pthread_join) silinseydi ne olurdu?
int kismi[2]; void *topla(void *arg) { int k = *(int *)arg; int ilk = 5 * k + 1; for (int i = ilk; i < ilk + 5; i++) kismi[k] += i; return NULL; } int main(void) { pthread_t t[2]; int no[2] = {0, 1}; for (int k = 0; k < 2; k++) pthread_create(&t[k], NULL, topla, &no[k]); for (int k = 0; k < 2; k++) pthread_join(t[k], NULL); int a = kismi[0], b = kismi[1]; printf("%d + %d = %d\n", a, b, a + b); return 0; }
Cevabı göster
15 + 40 = 55
k = 0 iş parçacığı 1…5’i (15), k = 1 iş parçacığı 6…10’u (40) toplar. Her biri dizinin farklı elemanına yazdığı için yarış yoktur; join ikisinin de bitmesini bekler.
join olmasa main iş parçacıkları bitmeden yazdırabilir (ör. 0 + 0 = 0 ya da yarım toplamlar) ve main’den dönüş tüm süreci, iş parçacıklarıyla birlikte sonlandırır.
Soru 17 · Adım Adım Çözüm
Soru 17: Adım Adım Çözüm
int kismi[2]; void *topla(void *arg) { int k = *(int *)arg; int ilk = 5 * k + 1; for (int i = ilk; i < ilk + 5; i++) kismi[k] += i; return NULL; } int main(void) { pthread_t t[2]; int no[2] = {0, 1}; for (int k = 0; k < 2; k++) pthread_create(&t[k], NULL, topla, &no[k]); for (int k = 0; k < 2; k++) pthread_join(t[k], NULL); int a = kismi[0], b = kismi[1]; printf("%d + %d = %d\n", a, b, a + b); return 0; }
k = 0: topla(&no[0]) için T0 oluşturulur.
k = 1: T1 oluşturulur. Artık main, T0 ve T1 eşzamanlı çalışabilir.
T0: i = 1…5 → kismi[0] = 15.
T1: i = 6…10 → kismi[1] = 40. Sıra fark etmez: ayrı elemanlar.
main iki join ile ikisinin de bittiğinden emin olur.
Çıktı: 15 + 40 = 55 (1’den 10’a toplam).
Soru 18 · Pthreads
İş Parçacığından Sonuç Almak
Kod izleme Program ne yazdırır? kare içinde int s = x * x; return &s; yazılsaydı ne olurdu?
void *kare(void *arg) { int x = *(int *)arg; int *s = malloc(sizeof(int)); *s = x * x; return s; } int main(void) { pthread_t t[3]; int a[3] = {2, 3, 5}, top = 0; void *r; for (int i = 0; i < 3; i++) pthread_create(&t[i], NULL, kare, &a[i]); for (int i = 0; i < 3; i++) { pthread_join(t[i], &r); top += *(int *)r; free(r); } printf("top=%d\n", top); }
Cevabı göster
top=38
4 + 9 + 25 = 38. Her iş parçacığı sonucunu öbekte ayırdığı alana yazar; pthread_join bu göstericiyi r’ye verir, main toplayıp belleği serbest bırakır.
&s döndürmek hatadır: s iş parçacığının yığınındadır; iş parçacığı bitince o yığın çerçevesi geçersizleşir ve main sarkan bir göstericiyi okur (tanımsız davranış).
Soru 19 · Pthreads
Aynı Adresi Paylaşan Argüman
Çoktan seçmeli Programcı ekranda 0 1 2 görmeyi bekliyor. Hangisi doğrudur?
void *yaz(void *arg) { printf("%d ", *(int *)arg); return NULL; } int main(void) { pthread_t t[3]; for (int i = 0; i < 3; i++) pthread_create(&t[i], NULL, yaz, &i); for (int j = 0; j < 3; j++) pthread_join(t[j], NULL); return 0; }
- Her zaman
0 1 2yazar - Her zaman
3 3 3yazar - Çıktı belirsizdir: üç iş parçacığı da aynı
ideğişkeninin adresini alır ve onu okudukları andaideğişmiş olabilir - Derleme hatası verir
Cevabı göster
Doğru cevap: C · Çıktı belirsizdir: üç iş parçacığı da aynı i değişkeninin adresini alır ve onu okudukları anda i değişmiş olabilir
1 1 3, 2 3 3 gibi çıktılar görülebilir; döngü bittikten sonra i’nin ömrü de dolduğundan okumak tanımsız davranıştır. Çözüm: her iş parçacığına ayrı bir bellek alanı vermek (int no[3] dizisi ve &no[i]) ya da değeri göstericiye gömmek.
Soru 20 · Örtük İş Parçacığı
İş Parçacığı Havuzunun Sonucu Değil
Çoktan seçmeli Bir web sunucusu her istek için yeni iş parçacığı oluşturmak yerine 16 iş parçacıklı bir havuz kullanıyor. Aşağıdakilerden hangisi bu tercihin bir sonucu değildir?
- Her istek kendi korumalı adres uzayında, diğerlerinden yalıtılmış çalışır
- Aynı anda çalışan iş parçacığı sayısı sınırlanır; ani yük sistemi kaynaksız bırakmaz
- Görevi tanımlamak ile görevin nasıl çalıştırılacağı birbirinden ayrılır
- İş parçacığı oluşturma ve yok etme maliyeti her istekte yeniden ödenmez
Cevabı göster
Doğru cevap: A · Her istek kendi korumalı adres uzayında, diğerlerinden yalıtılmış çalışır
Havuzdaki iş parçacıkları aynı sürecin adres uzayını paylaşır; havuz yalıtım getirmez. Getirdikleri: hazır iş parçacığıyla daha hızlı hizmet, eşzamanlılık üst sınırı ve ExecutorService gibi görev–yürütme ayrımı. Fazla istekler kuyrukta bekler.
Soru 21 · Örtük İş Parçacığı
Havuz Ne Kadar Büyük Olmalı?
Açık uçlu 8 çekirdekli bir makinede iki ayrı havuz kurulacak: biri yalnızca hesap yapan (CPU’ya bağlı) görüntü sıkıştırma görevleri, diğeri zamanının çoğunu veritabanı yanıtı bekleyerek geçiren (G/Ç’ye bağlı) istekler için. Havuz boyutlarını nasıl seçersiniz? Gerekçelendirin.
Cevabı göster
- CPU’ya bağlı: yaklaşık çekirdek sayısı kadar (8 ya da 9). Fazlası paralellik kazandırmaz, yalnızca bağlam değiştirme ve önbellek çekişmesi ekler.
- G/Ç’ye bağlı: çekirdek sayısından çok daha büyük. Kaba kural: Niş ≈ Nçekirdek × (1 + bekleme / hesap). Ör. bekleme/hesap = 9 ise 8 × 10 = 80.
Boyut ölçümle ayarlanmalıdır; çok büyük havuz bellek tüketir, çok küçük havuz CPU’yu boş bırakır.
Soru 22 · Örtük İş Parçacığı
OpenMP Paralel Bölge
Çoktan seçmeli Program -fopenmp ile derlenip çalıştırılıyor. Çıktı hakkında hangisi doğrudur?
#include <omp.h> #include <stdio.h> int main(void) { #pragma omp parallel num_threads(3) printf("merhaba\n"); printf("bitti\n"); return 0; }
merhaba1 kez,bitti1 kezmerhaba3 kez (herhangi bir sırada), ardındanbitti1 kez- Her ikisi de 3 kez, iç içe geçmiş biçimde
merhabaçekirdek sayısı kadar,bittihiç
Cevabı göster
Doğru cevap: B · merhaba 3 kez (herhangi bir sırada), ardından bitti 1 kez
#pragma omp parallel yalnızca izleyen tek deyime uygulanır: 3 iş parçacığından oluşan bir ekip oluşur, her biri printf("merhaba") çalıştırır. Bölgenin sonunda örtük bir bariyer vardır; ardından yalnızca ana iş parçacığı bitti yazar. Bu örtük (implicit) iş parçacığının tipik örneğidir: iş parçacıklarını derleyici ve çalışma zamanı oluşturur.
Soru 23 · Örtük İş Parçacığı
Boşta Kalan İşçi Ne Yapar?
Çoktan seçmeli Fork-join tabanlı bir havuzda (ör. Java ForkJoinPool) her işçinin kendi görev kuyruğu var. Kuyruğu boşalan bir işçi ne yapar?
- Başka bir işçinin kuyruğunun diğer ucundan bir görev çalar
- Hemen sonlanır ve havuz küçülür
- Ana iş parçacığından yeni görev gelene kadar meşgul bekler
- Tüm işçileri durdurup görevleri yeniden dağıtır
Cevabı göster
Doğru cevap: A · Başka bir işçinin kuyruğunun diğer ucundan bir görev çalar
İş çalma (work stealing): işçi kendi kuyruğunun bir ucundan (LIFO) alır, hırsız diğer ucundan (FIFO) çalar; böylece çekişme azalır ve yük kendiliğinden dengelenir. Büyük alt görevler genelde kuyruğun eski ucunda olduğundan çalınan iş verimlidir.
Soru 24 · İş Parçacığı Sorunları
İş Parçacıklı Süreçte fork()
Çoktan seçmeli 8 iş parçacıklı bir süreçteki bir iş parçacığı fork() çağırıyor (POSIX/Linux). Çocuk süreçle ilgili hangisi doğrudur?
- Çocukta 8 iş parçacığının hepsi kopyalanmış olarak çalışır
- Çocukta hiç iş parçacığı yoktur, süreç hemen sonlanır
- Çocukta yalnızca
fork’u çağıran iş parçacığının kopyası vardır; diğerlerinin tuttuğu kilitler çocukta kilitli kalabilir forkçok iş parçacıklı süreçlerde her zaman hata döndürür
Cevabı göster
Doğru cevap: C · Çocukta yalnızca fork’u çağıran iş parçacığının kopyası vardır; diğerlerinin tuttuğu kilitler çocukta kilitli kalabilir
Adres uzayının tamamı kopyalanır, ama iş parçacıklarından yalnızca biri. Başka bir iş parçacığının tuttuğu bir mutex (ör. malloc içindeki) çocukta sonsuza dek kilitli kalabilir. Bu yüzden önerilen kullanım, fork’tan hemen sonra exec çağırmaktır; exec zaten tüm adres uzayını değiştirir.
Soru 25 · İş Parçacığı Sorunları
Ctrl+C Hangi İş Parçacığına?
Çoktan seçmeli Çok iş parçacıklı bir sürece terminalden SIGINT (Ctrl+C) gönderildi. POSIX’e göre sinyal nasıl teslim edilir?
- Her zaman tüm iş parçacıklarına ayrı ayrı
- Sinyaller çok iş parçacıklı süreçlerde yok sayılır
- Her zaman yalnızca main iş parçacığına
- Sürece yönelik sinyal, bu sinyali engellemeyen herhangi bir iş parçacığına teslim edilir
Cevabı göster
Doğru cevap: D · Sürece yönelik sinyal, bu sinyali engellemeyen herhangi bir iş parçacığına teslim edilir
Sinyal işleyicisi tüm sürece aittir, sinyal maskesi ise her iş parçacığına özeldir. Yaygın desen: tüm iş parçacıklarında sinyali engellemek, tek bir iş parçacığında sigwait ile beklemek. Belirli bir iş parçacığına göndermek için pthread_kill kullanılır; bellek hatası gibi eşzamanlı sinyaller ise hataya yol açan iş parçacığına gider.
Soru 26 · İş Parçacığı Sorunları
Hangi İptal Daha Güvenli?
Çoktan seçmeli Bir arama programında sonuç bulununca diğer arama iş parçacıkları iptal ediliyor. Ertelenmiş iptal neden eşzamansız iptale tercih edilir?
- Ertelenmiş iptalde hedef iş parçacığı iptal noktalarında durumunu denetler ve kilitleri, belleği tutarlı biçimde bırakarak sonlanır
- Ertelenmiş iptal iş parçacığını anında öldürdüğü için daha hızlıdır
- Eşzamansız iptal POSIX’te tanımlı değildir
- Ertelenmiş iptal iş parçacığını değil tüm süreci sonlandırır
Cevabı göster
Doğru cevap: A · Ertelenmiş iptalde hedef iş parçacığı iptal noktalarında durumunu denetler ve kilitleri, belleği tutarlı biçimde bırakarak sonlanır
Eşzamansız iptal iş parçacığını herhangi bir komutta kesebilir: bir kilidi tutarken ya da bir veri yapısını yarı güncellemişken. Ertelenmiş iptal (Pthreads varsayılanı) yalnızca pthread_testcancel ya da bazı bloke eden çağrılar gibi iptal noktalarında gerçekleşir ve temizlik işleyicileri çalışır.
Soru 27 · İş Parçacığı Sorunları
Her İş Parçacığına Ayrı Kopya
Çoktan seçmeli Her iş parçacığının kendi hata kodunu tutacağı, ama tüm fonksiyonlardan global gibi erişilebilen bir değişken gerekiyor (C’deki errno gibi). Hangisi kullanılır?
staticglobal değişken- İş parçacığına yerel depolama (
_Thread_local/__thread) - Öbekte tek bir
mallocile ayrılan değişken - Yerel (yığın) değişken
Cevabı göster
Doğru cevap: B · İş parçacığına yerel depolama (_Thread_local / __thread)
TLS değişkeni her iş parçacığında ayrı bir kopya olarak bulunur ve iş parçacığının ömrü boyunca yaşar. Global ve öbek değişkeni paylaşılır; yerel değişken ise fonksiyon dönünce kaybolur ve diğer fonksiyonlar ona erişemez.
Soru 28 · İş Parçacığı Sorunları
strtok Neden Sorunlu?
Çoktan seçmeli İki iş parçacığı farklı dizgeleri aynı anda strtok ile parçalıyor ve sonuçlar karışıyor. Neden?
strtokbir sistem çağrısıdır ve çekirdekte kilitlenir- Dizgeler yığında olduğu için iş parçacıkları onları göremez
strtokkaldığı yeri gizli birstaticdeğişkende tutar; iki iş parçacığı bu ortak durumu birbirinin üzerine yazarstrtokyalnızca main iş parçacığında çalışabilir
Cevabı göster
Doğru cevap: C · strtok kaldığı yeri gizli bir static değişkende tutar; iki iş parçacığı bu ortak durumu birbirinin üzerine yazar
strtok yeniden girilir (reentrant) değildir. Çözüm, durumu çağırana taşıyan strtok_r’dir: char *kalan; strtok_r(s, " ", &kalan);. Yeniden girilir fonksiyonlar paylaşılan durum tutmaz; böylece iş parçacığı güvenli de olurlar.
Soru 29 · İş Parçacığı Sorunları
Kaybolan Artırmalar
Hesaplama Paylaşılan sayac 0’dır. T1 ve T2 iş parçacıklarının her biri sayac++’ı iki kez çalıştırıyor; her artırma iki adımdır: oku (r = sayac) ve yaz (sayac = r + 1). Adımlar şu sırayla işlerse sayac’ın son değeri nedir? T1.oku, T2.oku, T2.yaz, T2.oku, T2.yaz, T1.yaz, T1.oku, T1.yaz. Olası tüm son değerler nelerdir?
Cevabı göster
Bu sırada son değer 2’dir: T1’in ilk okuduğu eski 0, T2’nin iki artırmasını ezer.
Tüm sıralamalar düşünüldüğünde son değer 2, 3 ya da 4 olabilir. Doğru sonuç (4) yalnızca artırmalar bölünmeden (atomik) yapılırsa garanti edilir: pthread_mutex_lock ile kritik bölge ya da atomic_fetch_add.
Soru 29 · Adım Adım Çözüm
Soru 29: Adım Adım Çözüm
1–2. T1.oku → r1 = 0; T2.oku → r2 = 0. İkisi de aynı eski değeri gördü.
3–5. T2.yaz → sayac = 1; T2.oku → r2 = 1; T2.yaz → sayac = 2. T2 iki artırmasını bitirdi.
6. T1.yaz → sayac = r1 + 1 = 1. T1’in bayat değeri T2’nin iki artırmasını ezdi.
7–8. T1.oku → r1 = 1; T1.yaz → sayac = 2.
Sonuç: 4 artırma yapıldı ama sayac = 2. En kötü sıralamada bile en az 2 olur (her iş parçacığının ikinci okuması en az 1 görür, dolayısıyla son yazma en az 2’dir); en iyi durumda 4.
Soru 30 · İş Parçacığı Sorunları
Linux’ta İş Parçacığı ile Süreç
Açık uçlu Linux çekirdeği süreç ile iş parçacığını ayrı yapılarla değil, tek bir “görev” (task) kavramıyla temsil eder. fork() ile pthread_create() arasındaki fark çekirdek düzeyinde nasıl ortaya çıkar?
Cevabı göster
İkisi de sonunda clone() sistem çağrısıyla yeni bir task_struct oluşturur; fark, hangi kaynakların paylaşılacağını belirten bayraklardadır.
fork: paylaşım bayrağı yok (yalnızcaSIGCHLD) → adres uzayı, dosya tablosu, sinyal işleyicileri kopyalanır (COW).pthread_create:CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_SIGHAND | CLONE_THREAD …→ bunlar ebeveynle paylaşılır, aynı iş parçacığı grubuna (aynı PID) girer.
Ara durumlar da mümkündür: konteynerler, yeni ad alanları isteyen bayraklarla (CLONE_NEWPID vb.) oluşturulur.
Özet
Özet: Sık Yapılan Hatalar
| Yanlış düşünce | Doğrusu |
|---|---|
| İş parçacıkları yığını da paylaşır. | Her iş parçacığının kendi yığını, PC’si ve yazmaçları vardır; paylaşılan kod, veri, öbek, dosyalardır. |
| Bir iş parçacığı çökerse yalnızca o biter. | Bellek hatası tüm süreci sonlandırır; yalıtım yoktur. |
| Tek çekirdekte iş parçacıkları paraleldir. | Tek çekirdekte yalnızca eşzamanlılık vardır. |
| N çekirdek N kat hızlandırır. | Amdahl: seri kısım S iken üst sınır 1/S’dir. |
| Bir iş parçacığı bloke olunca süreç her zaman durur. | Bu yalnızca N:1 modelinde olur; 1:1’de yalnızca çağıran bekler. |
| Döngü değişkeninin adresini argüman vermek güvenlidir. | Tüm iş parçacıkları aynı adresi okur; her birine ayrı alan verin. |
| Yerel değişkenin adresini döndürmek sorun değildir. | Yığın çerçevesi yok olur; sonucu öbekte ayırın. |
| fork() tüm iş parçacıklarını kopyalar. | Çocukta yalnızca çağıran iş parçacığı vardır; ardından exec önerilir. |