Download as pdf or txt
Download as pdf or txt
You are on page 1of 11

Başlamadan önce kısa bilgi

MUTEX: Turnikelere benzetebiliriz. Kart basmadan girilmez yada çıkılmaz ve o turnikeler giren çıkanı
sayar.

Konu: İşletim sistemlerinde aynı anda çalıştırılan programların ya da görevlerin algoritmasıyla


alakalıdır. Aşağıda sunulan sorun bir metafordur ve kafamızda daha iyi canlanmasını sağlamak
amacıyla yazılmıştır.

THREAD: İş parçacıkları olarak Türkçeleşir. Alt görev, alt iş ve küçük işler olarakta düşünelebilir.
Örneğin bir restaurantınız var ve hamburger yapmak istiyorsunuz. Asıl göreviniz Yemek pişirmek
genel olarak yemek pişiriyorsunuz bunların tümünü process olarak adlandırıyoruz. Hamburger siparişi
geldi ve hamburger pişirmeniz gerekiyor bu da bir thread’tır.

The Child Care Problem

Max Hailperin bu sorunu “Operating Systems and Middleware” ders kitabı için yazdı. Çocuk bakım
merkezlerinde, devlet yönetmelikleri gereği her üç çocuk başına 1 yetişkin olması gerekir.
Puzzle: Bu kısıtlamayı kritik bir bölümde zorlayan çocuk threadları ve yetişkin threadları için kod
yazın.
Max Hailperin wrote this problem for his textbook Operating Systems and Middleware . At a child
care center, state regulations require that there is always one adult present for every three children.
Puzzle: Write code for child threads and adult threads that enforces this constraint in a critical
section.

Child care hint

Hailperin, bu sorunu bir semafor ile neredeyse çözebileceğinizi önerir.


Hailperin suggests that you can almost solve this problem with one semaphore.

Multiplex, her çipin bir çocuğun giriş yapmasına izin verdiği kullanılabilir çip sayısını sayar. Yetişkinler
girdikçe üç kez multiplex ağ sinyali verirler; ayrıldıkları zaman üç kez beklerler. Ancak bu çözümle ilgili
bir sorun var.
Multiplex counts the number of tokens available, where each token allows a child thread to enter. As
adults enter, they signal multiplex three times; as they leave, they wait three times. But there is a
problem with this solution.

Puzzle: Sorun nedir?


Puzzle: what is the problem?

.
Child care non-solution

Hailperin'in non-solution çözümünde yetişkin kodunun nasıl göründüğüne bakalım:


Here is what the adult code looks like in Hailperin’s non-solution:

Sorun, olası bir deadlock (kitlenme, çıkmaz). Çocuk bakım merkezinde üç çocuk ve iki yetişkin
olduğunu hayal edin. Multiplex ağ değeri 3’tür, bu nedenle her iki yetişkinden biri ayrılabilmelidir.
Ancak her iki yetişkin de aynı anda ayrılmaya kalkarsa, mevcut belirteçleri aralarında ve iki blok
arasında ayırabilirler.
The problem is a potential deadlock. Imagine that there are three children and two adults in the child
care center. The value of multiplex is 3, so either adult should be able to leave. But if both adults
start to leave at the same time, they might divide the available tokens between them, and both
block.

Puzzle: Bu sorunu en az değişikle çözün.


Puzzle: solve this problem with a minimal change.

..

.
Child Care Solution

Mutex eklendiğinde sorun çözülür:


Adding a mutex solves the problem:

Şimdi üç bekleme işlemi bölünemez. Üç belirteç varsa, mutekste bulunan iş parçacığı üç belirteçin
tümünü alır ve çıkar. Daha az belirteç varsa, ilk iş parçacığı mutex içinde takılır ve sonraki iş
parçacıkları mutex üzerinde sıraya alınır.
Now the three wait operations are atomic. If there are three tokens available, the thread that gets
the mutex will get all three tokens and exit. If there are fewer tokens available, the first thread will
block in the mutex and subsequent threads will queue on the mutex.

Genişletilmiş Child-Care sorunu

Bu çözümün özelliği; ayrılmayı bekleyen bir yetişkinin, çocuğun girişini engelleyebilmesidir.


4 çocuk ve iki yetişkin olduğunu düşünelim bu yüzden multiplex değeri 2 olur.
Yetişkinlerden biri ayrılmaya çalışırsa iki jeton alır ve üçüncü tokeni elde edene kadar engellenir.
Bir çocuk geldiğinde, girmek yasal olsa bile bekleyecektir.
Ayrılmaya çalışan yetişkinin bakış açısından bu sorun olmayabilir, ancak çocuk bakım merkezinin
kullanımını en üst düzeye çıkarmaya çalışıyorsanız sorun teşkil eder.
One feature of this solution is that an adult thread waiting to leave can prevent child threads from
entering. Imagine that there are 4 children and two adults, so the value of the multiplex is 2. If one of
the adults tries to leave, she will take two tokens and then block waiting for the third. If a child
thread arrives, it will wait even though it would be legal to enter. From the point of view of the adult
trying to leave, that might be just fine, but if you are trying to maximize the utilization of the child
care center, it’s not.

Puzzle: Gereksiz beklemeyi önleyen bu soruna bir çözüm yazın.


İpucu: 3.8 Bölüm'deki dansçıları düşünün.
Puzzle: write a solution to this problem that avoids unnecessary waiting. Hint: think about the
dancers in Section 3.8.

.
Extended Child Care İpucusu

Çözümümde kullandığım değişkenler şunlardır:


Here are the variables I used in my solution:

Bekleyen ve ayrılan, yetişkin ve çocuklar; girmeyi bekleyen çocukların ve ayrılmayı bekleyen


yetişkinlerin sayısını tutar. Bunlar da mutex tarafından korunur.

Children, adult , waiting and leaving keep track of the number of children, adults, children waiting to
enter, and adults waiting to leave; they are protected by mutex.

Çocuklar, gerekirse, childQueue girilmesini bekler. Yetişkinler ayrılmak için adultQueue'da bekler.
Children wait on childQueue to enter, if necessary. Adults wait on adultQueue to leave.
Extended Child-Care Solution

Bu çözüm Hailperin'in elegant çözümünden daha karmaşıktır, ancak daha önce gördüğümüz kalıpların
kombinasyonudur: Bir skor tahtası, iki queue ve "bunu sizin için yapacağım". Bu çocuk için yazılan:
This solution is more complicated than Hailperin’s elegant solution, but it is mostly a combination of
patterns we have seen before: a scoreboard, two queues, and “I’ll do it for you”. Here is the child
code:

1.Çocuklar içeri girerken yeterli yetişkin olup olmadığını kontrol ederler


-ya çocukları arttır ya da artışı beklet ve engelle.
2.Çıkarken, ayrılmayı bekleyen bir yetişkinin olup olmadığını kontrol ederler ve mümkünse
sinyal verirler.
As children enter, they check whether there are enough adults and either (1) increment
children and enter or (2) increment waiting and block. When they exit, they check for an
adult thread waiting to leave and signal it if possible
Bu da yetişkin için yazılan:
Here is the code for adults:

Yetişkinler girdikçe, eğer varsa bekleyen çocuklara sinyal gönderirler. Ayrılmadan önce yeterli yetişkin
olup olmadığını kontrol ederler. Yetişkin sayısını azaltıp çıkış yaparlar. Aksi takdirde artıştan vazgeçer
ve bloklarlar. Yetişkin thread çıkış yapmayı beklerken kritik bölümdeki yetişkinlerden biri olarak sayılır
böylece ek çocuklar girebilir.
As adults enter, they signal waiting children, if any. Before they leave, they check whether there are
enough adults left. If so, they decrement adults and exit. Otherwise they increment leaving and
block. While an adult thread is waiting to leave, it counts as one of the adults in the critical section,
so additional children can enter.
1. #define __USE_GNU 1
2. #include <pthread.h>
3. #include <stdio.h>
4. #include <stdlib.h>
5. #include <unistd.h>
6. #include <semaphore.h>
7.
8. #define N_ITEMS 30
9.
10. // Tüm yetişkinleri ve tüm çocukları saklamak için buffer.
11. //Buffer, genellikle bilgisayarın belleğinde (RAM) kısa bir süre depolanan
veriler içerir.
12. int buffer_adult[N_ITEMS];
13. int buffer_child[3 * N_ITEMS];
14.
15. //Odada bulunan yetişkin ve çocukları tutan değişkenler.
16. int quantity_adult = 0, quantity_child = 0;
17.
18. // Yetişkin ve çocuklar için semafor (3 çocuk,1 yetişkin kuralı orantısı
için)
19. sem_t sem_adult;
20. sem_t sem_child;
21.
22. // Yetişkinlerin pozisyonlarını müsait olup olmadığını kontrol eden
semaforlar.
23. sem_t pos_empty_adult;
24. sem_t pos_bussy_adult;
25.
26. // Çocukların pozisyonlarını müsait olup olmadığını kontrol eden semaforlar.
27. sem_t pos_empty_child;
28. sem_t pos_bussy_child;
29.
30. //Geçici başlangıç değerleri.
31. int start_adult = 0, finish_adult = 0, finish_child = 0, finish_child = 0;
32.
33. //Odaya giren yetişkinler için fonksiyonumuz.
34. void* enter_adult(void *v) {
35.
36. int i;
37. for(i=0;i<N_ITEMS;i++){
38. sem_wait(&pos_empty_adult); //Yetişkinlerin pozisyonlarının ayarlanması
39. sem_wait(&sem_adult); //Yetişkin talebi
40.
41. //Yetişkin eklenir
42. quantity_adult += 1;
43. printf("Adult input, item = %d. just here quantity = %d\n", i, quantity_adult);
44. finish_adult = (finish_adult + 1) % N_ITEMS;
45. buffer_adult[finish_adult] = i;
46.
47. sem_post(&pos_bussy_adult); //Yetişkinin pozisyonunu 1 arttır.
48.
49. //Çocuk girişi için izin ver.(3 kez)
50. sem_post(&sem_child);
51. sem_post(&sem_child);
52. sem_post(&sem_child);
53.
54. sleep(random() % 3);
55. }
56.
57. return NULL;
58. }
59.
60. //Odaya giren çocuklar için fonksiyonumuz.
61. void* enter_child(void *v) {
62.
63. int quantity_child , i;
64. for(i=0;i< 3 * N_ITEMS;i++){
65. sem_wait(&pos_empty_child); //Çocukların pozisyonlarının ayarlanması.
66. sem_wait(&sem_child); //Çocuk talebi
67.
68. //Çocuk eklenir.
69. quantity_child += 1;
70. printf("Child input, item = %d. just here quantity = %d\n", i, quantity_child);
71. finish_child = (finish_child + 1) % (3 * N_ITEMS);
72. buffer_child[finish_child] = i;
73.
74. sem_post(&pos_bussy_child); //Çocuğun pozisyonunu 1 arttır.
75. sem_getvalue(&sem_child, &quantity_child); //Çocuk semaforunun değerini
yazdır.
76.
77. //Eğer izin verilen çocuk pozisyonu 0 ise yetişkin talep et.
78. if (quantity_child == 0){
79. sem_post(&sem_adult);
80. }
81.
82. sleep(random() % 2);
83. }
84.
85. return NULL;
86. }
87.
88. //Odadan çıkan yetişkinler için fonksiyonumuz.
89. void* exit_adult(void *v){
90.
91. int i, j;
92.
93. for (i = 0; i < N_ITEMS; i++){
94. sem_wait(&pos_bussy_adult); //Yetişkinlerin pozisyonlarının ayarlanması
95.
96. //Koşul sağlandığı sürece döndür (child>(3*adult-1))
97. while (quantity_child > 3 * (quantity_adult - 1));
98. for (j = 0; j < 3; j++){
99. sem_wait(&sem_child); //Çocuk semaforunu 1 azalt.
100. }
101.
102. //Bir yetişkini serbest bırakıyoruz.
103. start_adult = (start_adult + 1) % N_ITEMS;
104. quantity_adult -= 1;
105. printf("Leaving adult, item = %d. just here quantity = %d\n",
buffer_adult[start_adult], quantity_adult);
106.
107. sem_post(&pos_empty_adult); //Boşta olan yetişkin pozisyonunu 1
arttırıyoruz.
108.
109. //Eğer hiç yetişkin yok yada bütün yetişkinler meşgul ise yetişkin
talep et
110. if ((quantity_adult <= 0)||(3 * quantity_adult == quantity_child))
111. sem_post(&sem_adult);
112.
113. sleep(random() % 10);
114. }
115. return NULL;
116. }
117.
118.
119. //Odadan çıkan çocuklar için fonksiyonumuz.
120. void* exit_child(void *v){
121. int i, j;
122.
123. for (i = 0; i < N_ITEMS; i++){
124. sem_wait(&pos_bussy_child); //Çocuk yoğunluğunu 1 azalt
125. //Çocuğu çıkart
126. finish_child = (finish_child + 1) % (3 * N_ITEMS);
127. quantity_child -= 1;
128. printf("Leaving child, item = %d. just here quantity = %d\n",
buffer_child[finish_child], quantity_child);
129.
130. sem_post(&pos_empty_child); //Boşta olan çocuk pozisyonunu 1 arttır.
131.
132. //Koşul sağlandıkça Yetişkini bırak, çocuğu çıkart ((3*adult-
1)>child))
133. while ((quantity_adult - 1) * 3 - 1 >= quantity_child){
134. sem_wait(&pos_bussy_adult); //Meşgul yetişkin pozisyonunu 1 azalt.
135. for (j = 0; j < 3; j++){
136. sem_wait(&sem_child); //Çocuk sayısını 1 azalt.
137. }
138. start_adult = (start_adult + 1) % N_ITEMS;
139. quantity_adult -= 1;
140. printf("\n--by forcing,pulled out adult, item %d. just here quantity =
%d\n\n", buffer_adult[start_adult], quantity_adult);
141. }
142. sem_post(&sem_child); //Çocuk sayısını arttır.
143. sleep(random() % 13);
144. }
145. return NULL;
146. }
147.
148.
149. //Main fonksiyonumuz.
150. int main(){
151.
152. //Thread bildirimi
153. pthread_t thr_enter_adult, thr_enter_child, thr_exit_adult,
thr_exit_child;
154. //Tüm Semaforları başlatma
155. sem_init(&sem_child, 0, 0);
156. sem_init(&sem_adult, 0, 1);
157. sem_init(&pos_empty_adult, 0, N_ITEMS);
158. sem_init(&pos_bussy_adult, 0, 0);
159.
160. sem_init(&pos_empty_child, 0, (3 * N_ITEMS));
161. sem_init(&pos_bussy_child, 0, 0); //Fonksiyonları threadlara atama
162. pthread_create(&thr_enter_adult, NULL, enter_adult, NULL);
163. pthread_create(&thr_enter_child, NULL, enter_child, NULL);
164. pthread_create(&thr_exit_adult, NULL, exit_adult, NULL);
165. pthread_create(&thr_exit_child, NULL, exit_child, NULL);
166.
167. //Fonksiyonları threadlere joinleme
168. pthread_join(thr_enter_adult, NULL);
169. pthread_join(thr_enter_child, NULL);
170. pthread_join(thr_exit_adult, NULL);
171. pthread_join(thr_exit_child, NULL);
172.
173. //Semaforları yok et
174. sem_destroy(&sem_child);
175. sem_destroy(&sem_adult);
176. sem_destroy(&pos_bussy_adult);
177. sem_destroy(&pos_empty_adult);
178. sem_destroy(&pos_bussy_child);
179. sem_destroy(&pos_empty_child);
180.
181. return 0;

You might also like