Yazan : Şadi Evren ŞEKER
Problemin tanımı : Bir berber dükkanında, bir bekleme salonu, bu salonda n adet sandelye ve ayrıca m adet berber koltuğu bulunmaktadır. Sistemimizde m adet de berber olduğunu düşünelim. Şayet hiç bekleyen müşteri yoksa berber uyumaya gider (diğer berberlerin traş ettiği müşterileri beklemesine gerek yoktur). Şayet bekleme salonundaki bütün sandelyeler doluyken bir müşteri içeri girerse, salon dolu olduğu için müşteri salonu terk eder (müşteri kaybedilmiş olur). Şayet berber o sırada birisini traş ediyorsa ama boş sandelye varsa, içeri giren kişi, boş sandelyelerden birisine oturur. Şayet berber uyurken bir müşteri girerse, müşteri berberi uyandırır. Bizden istenen bu problemin çözümünü yapan kodu (berber ve müşteri tarafları için) kodlamamız.
Şekilde görüldüğü üzere bir berber salonunda, n adet bekleme koltuğu ve n adet berber koltuğu şeklinde problem düşünülebilir.
Çözüm:
Problem tanımında bulunan ve senkronize edilmesi gereken durumları bulalım. Öncelikle problemimizde biribirini dışlama (mutually exclusion) problemi bulunmaktadır. Problem tanımındaki birden fazla işlemin (process) birbiri ile yarış durumuna (racing condition) girmesi halinde bazı kaynaklarda problem yaşanabilir. Örneğin aynı sandalyeye birden fazla müşterinin oturması veya berber koltuğuna birden fazla müşterinin oturması veya bir müşteri berber koltuğuna diğer müşteri kalkmadan oturmaya çalışırsa bu durumda yaşanacak problemler gibi çok sayıda problem bulunmaktadır.
Bu problemlerin en hızlı ve doğru çözümü birbirini dışlar şekilde (mutex) işlemlerin senkronize edilmesidir. Diğer bir deyişle aynı anda tek bir işlemin çalışmasına izin verilirse problem çözülür.
Öncelikle tasarımımızda semafor kullanacağız (semaphore). Problemimizde iki yaklaşımı çözmemiz gerekiyor. Birisi daha önce bahsedilen mutex diğeri ise problemin ilerlemesi açısından berber ve müşteri işlemleri (process) arasındaki ilişki. İki problem için de semafor kullanalım. Bu durumda çözüm aşağıdaki şekilde olur:
sem_init(&mutex,0,1); sem_init(&musteri,0,0); sem_init(&berberler,0,1); void berber(void *arg)/*Berber Process*/ { sem_wait(&musteri); sem_wait(&mutex); sayac--; printf("Barber:saçı kesilen:%d. kişin",sayac); sem_post(&mutex); sem_post(&berberler); sleep(3); // burada müşteriyi traş ediyor } void musteri(void *arg)/*musteri Process*/ { sem_wait(&mutex); if(sayac<N){ sayac++; printf("Bekleyen musteri sayisi :%d oldun",sayac); sem_post(&mutex); sem_post(&customer); sem_wait(&berberler); printf(“Müşteri: traş oldum”); } else{ printf(“Musteriyi kaybettik”); sem_post(&mutex); } sleep(1); }
Yukarıdaki çözümde, N sayısı, bekleme salonundaki sandeyle sayısını belirtmektedir. Sayac değişkeni anlık olarak kaç müşterinin salonda olduğunu belirtmektedir. Ayrıca aynı anda bir adet müşteri veya berber çalışabilmektedir. (mutex çözümünden dolayı)
Her iki işleminden bşalangıcında sem_wait(&mutex) satırı bulunmakta (dolayısıyla çalışan işlem her kim olursa olsun (berber ya da müşteri) o anda başka bir işlemin çalışmasına izin verilmemektedir. ) ve iki işlemin de çıkışnda sem_post(&mutex) bulunmaktadır. Bu durumda bir işlem bittikten sonra diğer işlemler çalışabilmektedir.
Şayet müşteri tarafındaki müşteri sayısı N’den küçükse, bekleme salonunda yer var demektir. Şayet daha büyükse yer yok demektir. Bu durumda müşteri kaybederiz. Dikkat edilirse müşteri fonksiyonunda iki durumda da çıkışta sem_post(&mutex) yapılmaktadır.
Ancak şayet yer varsa (sayac < N durumu) ve müşteri salona alınırsa (sayac++ yapılmış demektir) ve boş berber varsa bu durumda müşteri traş olur.
Bu tasarım sorunun çözümü açısından doğrudur ve senkronizasyon başarılı bir şekilde yapılmıştır. Ancak bu çözümde problem olacak bir durum müşterilerin geliş sırasının dikkate alınmamasıdır. Örneğin salona ilk gelen ve bekleyen müşteriye sıra henüz gelmeden sonradan gelen müşteriler traş olup çıkabilir. Yani salonda bekleyen bütün müşteriler aynı derecede değerlendirilmektedir. Şayet sıra dikkate alınmak isteniyorsa, bu durumda sıra teorisi (queueuing theory) kullanılmalıdır ve bu sorunun kapsamı dışındadır. Ancak burada bir kıtlık durumu (starvation) söz konusu olduğu bilinmelidir.
Yukarıda çözülmüş diğer bir problem ise, müşterilerin berber, berberlerin de müşteri beklemesi durumudur. Buna göre bir müşteri traş olmak için öncelikle boş bir berber bulmalıdır. Bu durum müşteri fonksiyonunda sem_wait(&berber) olarak belirtilmiştir. Aynı şekilde bir berber de traş etmek için bir müşteri beklemektedir. Bu durumda berber fonksiyonunda sem_wait(&musteri) olarak belirtilmiştir. Bu bekleme durumları da sem_post fonksiyonları ile çözülür. Şöyle ki bir müşteri geldiğinde sem_post(&musteri) çağrılarak müşteriyi bekleyen berberler uyandırılır, bir müşteri traş olup berber koltuğundan ayrıldığında da sem_post(&berber) denilerek o anda boşalan bir berber koltuğu (veya berber) olduğu haber verilir. Örneğin bir berber boşaldığı zaman, bekleme salonunda bulunan müşteriler yarış durumuna (racing condition) geçerler, aralarından ilk çalışan ve yarışı kazananı traş olmak için berber koltuğuna oturur. Şayet hiç müşteri yoksa yani salon boşsa, berber uyumaya gider.
Diğer İşletim Sistemi Senkronizasyon Problemleri ve Çözümleri: