{"id":335,"date":"2015-11-18T01:54:31","date_gmt":"2015-11-17T23:54:31","guid":{"rendered":"http:\/\/oguzkartal.net\/blog\/?p=335"},"modified":"2021-10-31T16:05:13","modified_gmt":"2021-10-31T13:05:13","slug":"concurrent-eszamanli-programlama-ve-race-condition-tehlikesi","status":"publish","type":"post","link":"https:\/\/www.oguzkartal.net\/blog\/index.php\/2015\/11\/18\/concurrent-eszamanli-programlama-ve-race-condition-tehlikesi\/","title":{"rendered":"Concurrent (Eszamanl\u0131) Programlama ve Race Condition Tehlikesi"},"content":{"rendered":"<p>Programlama ve programlama tekniklerinin geli\u015fimi, teknolojinin geli\u015fimiyle do\u011fru orant\u0131l\u0131 olarak de\u011fi\u015fim g\u00f6stermi\u015ftir. Kullan\u0131lan donan\u0131mlar daha g\u00fc\u00e7l\u00fc \u00f6zellikler sunduk\u00e7a bu onlar\u0131n tasar\u0131mlar\u0131n\u0131 da komplike bir hale getirmi\u015f ve bu donan\u0131mlar \u00fczerinde \u00e7al\u0131\u015fan yaz\u0131l\u0131mlar\u0131n da ona uygun \u015fekilde yeniden tasarlanmalar\u0131n\u0131 zorunlu k\u0131lm\u0131\u015ft\u0131r. \u00d6rne\u011fin bug\u00fcn multi-core yahut multi-processor (\u0130kisi aras\u0131nda fiziksel fark mevcuttur. Multiprocessor birden fazla fiziksel i\u015flemciyi ifade ederken, multi-core ayn\u0131 fiziksel i\u015flemci i\u00e7erisindeki birden fazla i\u015flem birimi \u00e7ekirde\u011fini ifade eder.) sistemler \u00fczerinde \u00e7al\u0131\u015fan i\u015fletim sistemleri i\u00e7in yaz\u0131l\u0131m geli\u015ftiren ki\u015fi, multitasking \u00f6zelli\u011fi olmayan DOS i\u00e7in yaz\u0131l\u0131m geli\u015ftiren bir ki\u015fiden daha fazla \u015feyi g\u00f6z \u00f6n\u00fcnde bulundurmak, yaz\u0131l\u0131m\u0131n\u0131n tasar\u0131m\u0131n\u0131 ona g\u00f6re yapmak zorundad\u0131r.<\/p>\n<p>\u00c7ok \u00e7ekirdekli yahut \u00e7ok i\u015flemcili sistemler ile beraber concurrency (e\u015fzamanl\u0131l\u0131k) terimi de anlam kazanmaya ba\u015flad\u0131. \u00c7\u00fcnk\u00fc bu t\u00fcr i\u015flemci teknolojileri ayn\u0131 zaman diliminde birden fazla komutu paralel olarak \u00e7al\u0131\u015ft\u0131rabilme yeteneklerine sahipler. Esas problemi olu\u015fturan k\u0131s\u0131m i\u015flemci taraf\u0131ndan ziyade verilerin depoland\u0131\u011f\u0131 belle\u011fin tek olmas\u0131 ve bu belle\u011fe eri\u015fimin i\u015flemciler taraf\u0131ndan ayn\u0131 veriyolu (bus) \u00fczerinden yap\u0131l\u0131yor olmas\u0131d\u0131r. B\u00f6yle bir durumda bellek bir payla\u015f\u0131lan kaynak konumundad\u0131r. Payla\u015f\u0131lan bir kayna\u011fa, e\u015fzamanl\u0131 \u00e7al\u0131\u015fan i\u015flemcilerin eri\u015fmeye \u00e7al\u0131\u015fmas\u0131 i\u015fin programlama k\u0131sm\u0131nda ba\u015f edilmesi gereken bir dizi problemi beraberinde getirir. Yaln\u0131z bu durum sorunun en b\u00fcy\u00fck sebebi olsa da tek sebebi de\u011fildir. Geli\u015fen i\u015fletim sistemi tasar\u0131mlar\u0131n\u0131n payla\u015f\u0131ml\u0131 kayna\u011fa eri\u015fmekte getirdi\u011fi benzer problemler de mevcut.\u00a0 Buna yaz\u0131n\u0131n ilerleyen k\u0131sm\u0131nda s\u0131ras\u0131 geldi\u011finde de\u011finece\u011fim. Ve o nokta da olduk\u00e7a \u00f6nem ta\u015f\u0131maktad\u0131r. Her ne kadar da multiprocessor sistemler s\u00f6z konusu olsa da uniprocessor (tek i\u015flemcili) sistemlerde bir\u00e7ok modern i\u015fletim sistemi multi-threading sa\u011flamaktayd\u0131. \u015eimdilik not olarak ge\u00e7eyim.<\/p>\n<h3>Race Condition<\/h3>\n<p>Race condition terimi iki ba\u011f\u0131ms\u0131z e\u015f s\u00fcrecin (Process) ayn\u0131 kaynak \u00fczerine ayn\u0131 zaman diliminde eri\u015fmeye \u00e7al\u0131\u015fmas\u0131 sonucu bir s\u00fcrecin di\u011ferinden \u00f6nce o kayna\u011fa eri\u015fip farkl\u0131 sonu\u00e7lar \u00fcretmesine yol a\u00e7an durumu tan\u0131mlamaktad\u0131r. Bu terimin genel bilinen bir T\u00fcrk\u00e7e kar\u015f\u0131l\u0131\u011f\u0131 yok. Biraz T\u00fcrk\u00e7e&#8217;ye do\u011frudan \u00e7evrilmesi s\u0131k\u0131nt\u0131l\u0131 manas\u0131z bir s\u00f6z \u00f6be\u011fine sebebiyet verebilir. O y\u00fczden ben de buna race condition demekle yetinece\u011fim. Ancak \u015funu s\u00f6yleyebilirim. \u0130ki e\u015f s\u00fcrecin ayn\u0131 zaman diliminde bir kayna\u011fa eri\u015fmesini bir yar\u0131\u015fa, bir m\u00fccadeleye benzetirsek bu <strong>m\u00fccadele durumu<\/strong>nun race condition terimiyle olan ba\u011flant\u0131s\u0131n\u0131 kafan\u0131zda san\u0131r\u0131m bir yere oturtabilirsiniz.<\/p>\n<p>Her ne kadar da \u00e7oklu i\u015flemcilerde e\u015f zamanl\u0131l\u0131k mevcutsa da s\u00f6z konusu tek bir kayna\u011fa ayn\u0131 veriyolu \u00fczerinden eri\u015fim oldu\u011fundan iki e\u015f s\u00fcre\u00e7ten biri ayn\u0131 zaman diliminde kayna\u011fa eri\u015fim sa\u011flamaktad\u0131r. Yaln\u0131z bu i\u015flemler nanosaniyeler \u00f6l\u00e7e\u011finde olup bitmektedir. 1 saniyenin 1000.000.000 (bir milyar) nanosaniyeye e\u015fit oldu\u011funu unutmay\u0131n.<\/p>\n<p>Race condition&#8217;\u0131 daha s\u0131k\u0131nt\u0131l\u0131 hale getiren bir durum daha vard\u0131r ki o da race condition&#8217;lar\u0131n rastgele meydana gelmesidir. Race condition&#8217;lar\u0131n ne zaman olu\u015faca\u011f\u0131n\u0131 tahmin edemezsiniz. Bir program yeterince \u015fansl\u0131 ise race condition olu\u015fmadan belki haftalarca d\u00fczg\u00fcn bir \u015fekilde \u00e7al\u0131\u015fabilir. Ancak bu onun hi\u00e7 olu\u015fmayaca\u011f\u0131 anlam\u0131na gelmez. Bu kesinlikle garanti de\u011fildir. \u00c7\u00fcnk\u00fc race condition&#8217;a zemin haz\u0131rlayan \u015fartlar tamamen i\u015flemciler \u00fczerinden \u00e7al\u0131\u015fan di\u011fer s\u00fcre\u00e7lerin zamanlanmas\u0131na ba\u011fl\u0131d\u0131r. Race condition olu\u015ftu\u011funda \u015fartlar \u00f6yle bir haldedir ki her iki i\u015flemci ayn\u0131 s\u00fcreci ayn\u0131 anda i\u015fletmeye \u00e7al\u0131\u015fmaktad\u0131r. E\u011fer i\u015fletim sistemi o s\u0131rada farkl\u0131 s\u00fcre\u00e7leri \u00e7al\u0131\u015ft\u0131rmaktaysa elbette bu ihtimal s\u0131f\u0131ra yak\u0131n ancak s\u0131f\u0131r de\u011fildir.<\/p>\n<p>\u015eimdi bu anlat\u0131lan\u0131 bir kod \u00fczerinde \u00f6rnekleyeyim. \u00d6rnekte bir adet payla\u015f\u0131ml\u0131 bir de\u011fi\u015fken olsun. Ve e\u015fzamanl\u0131 \u00e7al\u0131\u015facak 2 adet s\u00fcrecimiz olsun. Yapt\u0131\u011f\u0131 i\u015f bu payla\u015f\u0131ml\u0131 de\u011feri +1 kadar artt\u0131rmak olsun.<\/p>\n<pre class=\"lang:c decode:true\">int g_sharedValue = 0;\r\n\r\nvoid work()\r\n{\r\n\tint iteration=5;\r\n\t\r\n\twhile (iteration-- &gt; 0) \r\n\t{\r\n\t\tg_sharedValue++;\r\n\t}\r\n}\r\n\r\nvoid start()\r\n{\r\n\tconst int WORKER_COUNT=5;\r\n\t\r\n\tfor (int i=0;i&lt;WORKER_COUNT;i++)\r\n\t{\r\n\t\tcreate_worker(work);\r\n\t}\r\n}<\/pre>\n<p>\u015eimdi yukar\u0131daki misal verilen kod 5 farkl\u0131 i\u015f par\u00e7ac\u0131\u011f\u0131 (Thread) i\u00e7inde <strong>work<\/strong> ad\u0131nda bir fonksiyonu \u00e7al\u0131\u015ft\u0131r\u0131yorlar. Ve create_worker fonksiyonunu da her bir work fonksiyonunu farkl\u0131 processorlar \u00fczerinde \u00e7al\u0131\u015ft\u0131rd\u0131\u011f\u0131n\u0131 d\u00fc\u015f\u00fcn\u00fcn yeter. Dikkatinizi esas i\u015fi yapan work fonksiyonuna verin. \u015eimdi normal \u015fartlarda beklentimiz \u015fu \u015fekilde olur. Elimizde 5 adet thread (i\u015f par\u00e7ac\u0131\u011f\u0131) var. Ve bu 5 farkl\u0131 s\u00fcre\u00e7 kendi i\u00e7inde 5&#8217;er defa payla\u015f\u0131ml\u0131 olan <span class=\"lang:c decode:true  crayon-inline \">g_sharedValue<\/span> adl\u0131 de\u011fi\u015fkenimizi +1 artt\u0131r\u0131yor. Bizim beklentimiz bu program \u00e7al\u0131\u015f\u0131p sonland\u0131\u011f\u0131nda <span class=\"lang:c decode:true  crayon-inline \">g_sharedValue<\/span> de\u011fi\u015fkeninin <strong>25\u00a0<\/strong>de\u011ferini tutuyor olmas\u0131. Ancak program\u0131 defalarca \u00e7al\u0131\u015ft\u0131rd\u0131\u011f\u0131m\u0131zda \u015fu \u015fekilde sonu\u00e7lar almam\u0131z olas\u0131d\u0131r.<\/p>\n<p>1.\u00a0\u00a0 \u00e7al\u0131\u015fma: 25<br \/>\n2.\u00a0\u00a0 \u00e7al\u0131\u015fma: 25<br \/>\n3.\u00a0\u00a0 \u00e7al\u0131\u015fma: 25<br \/>\n4.\u00a0\u00a0 \u00e7al\u0131\u015fma: 25<br \/>\n5.\u00a0\u00a0 \u00e7al\u0131\u015fma: 25<br \/>\n6. \u00a0 \u00e7al\u0131\u015fma: <strong>23<\/strong><br \/>\n7.\u00a0\u00a0 \u00e7al\u0131\u015fma: 25<br \/>\n8.\u00a0\u00a0 \u00e7al\u0131\u015fma: 25<br \/>\n9.\u00a0\u00a0 \u00e7al\u0131\u015fma: <strong>24<br \/>\n<\/strong>10. \u00e7al\u0131\u015fma: 25<\/p>\n<p>\u00c7o\u011funlukta bekledi\u011fimiz sonucu alsak da aralarda \u00e7ok farkl\u0131 sonu\u00e7lar alabildik. \u0130\u015fte bu duruma sebebiyet veren durum Race condition&#8217;\u0131n tam olarak kar\u015f\u0131l\u0131\u011f\u0131d\u0131r. Peki nas\u0131l oluyor da d\u00f6ng\u00fc i\u00e7inde \u00e7al\u0131\u015fan bu kod eksik sayabiliyor? Bunu yukar\u0131da yaz\u0131ya giri\u015f k\u0131sm\u0131nda bahsetti\u011fim olay\u0131 birazc\u0131k grafi\u011fe d\u00f6kerek biraz detayland\u0131rarak anlatmak gerekecek.<\/p>\n<p>\u0130\u015flemciler programlad\u0131\u011f\u0131m\u0131z i\u015flemleri yapmak i\u00e7in yazd\u0131\u011f\u0131m\u0131z programlara kar\u015f\u0131l\u0131k gelen bir dizi makine komutu dizilerini \u00e7al\u0131\u015ft\u0131rmak durumundad\u0131rlar. Her ne kadar da biz makine komutlar\u0131na g\u00f6re y\u00fcksek seviye say\u0131lacak dillerde bu i\u015flemleri bir b\u00fct\u00fcn halinde \u00e7al\u0131\u015faca\u011f\u0131n\u0131 d\u00fc\u015f\u00fcnsek de bu kodlar\u0131n makine kodu kar\u015f\u0131l\u0131klar\u0131 birka\u00e7 ad\u0131mdan meydana gelebilir.<\/p>\n<p>Yukar\u0131daki \u00f6rne\u011fimizde bir de\u011fi\u015fkeni bir artt\u0131ran kod i\u015flemcinin perspektifinden \u015fu ad\u0131mlarla ger\u00e7ekle\u015fir. Bu ad\u0131mlar i\u015flemci mimarisinden mimarisine de\u011fi\u015fse de genel olarak hemen hepsinde ayn\u0131 yol izlenir. \u0130\u015flemciler bir bellek b\u00f6lgesinde bir de\u011fer \u00fczerinde de\u011fi\u015fikli\u011fe gidece\u011fi zaman bunu do\u011frudan bellek \u00fczerinde yapamazlar. \u00d6nce bellek b\u00f6lgesinden veriyi i\u00e7sel yazma\u00e7lar\u0131na (Registers) almal\u0131 (Load), yazma\u00e7lar \u00fczerinde gerekli de\u011fi\u015fiklik yap\u0131ld\u0131ktan sonra tekrar bellek b\u00f6lgesine yaz\u0131lmal\u0131d\u0131r (Store).<\/p>\n<p>Yani <span class=\"lang:c decode:true  crayon-inline \">g_sharedValue++<\/span> operasyonu i\u015flemci \u00fczerinde \u015fu ad\u0131mlarla ger\u00e7ekle\u015fir.<\/p>\n<p>1 &#8211; REGISTER1 = [g_sharedValue]\u00a0\u00a0\u00a0 \/\/g_sharedValue de\u011fi\u015fken adresindeki de\u011feri 1 nolu yazmaca y\u00fckle<br \/>\n2 &#8211; REGISTER1 = REGISTER1 + 1 \/\/yazma\u00e7 de\u011ferini 1 artt\u0131r.<br \/>\n3 &#8211; [g_sharedValue] = REGISTER1 \/\/yazma\u00e7taki de\u011feri geri bellek b\u00f6lgesine depola.<\/p>\n<p>\u015eimdi bakt\u0131\u011f\u0131m\u0131zda bizim a\u00e7\u0131m\u0131zdan tek ad\u0131mda halledilen bir kodun esasen 3 ayr\u0131 ad\u0131mdan meydana geldi\u011fini g\u00f6rd\u00fck. Bu noktada bir kavramdan daha bahsetmem gerek. O da <span style=\"color: #000000;\"><strong>Atomicity (B\u00f6l\u00fcnmezlik) <\/strong><\/span>dir. Atomicity yani b\u00f6l\u00fcnmezlik i\u015flemci \u00fczerindeki bir makine komut \u00e7al\u0131\u015f\u0131rken onu hi\u00e7bir ba\u015fka komutun araya girip b\u00f6lememesi demektir. \u00d6rne\u011fin yukar\u0131daki her bir ad\u0131m birer atomic operasyondur. Yani \u00e7al\u0131\u015fmalar\u0131 asla b\u00f6l\u00fcnemez.<\/p>\n<p><span style=\"color: #ff0000;\"><strong><a href=\"http:\/\/oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/Warning-icon.png\"><img loading=\"lazy\" decoding=\"async\" class=\"  wp-image-351 alignleft\" src=\"http:\/\/oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/Warning-icon.png\" alt=\"Warning-icon\" width=\"32\" height=\"32\" \/><\/a> D\u0130KKAT: <\/strong><\/span>Baz\u0131 tek instruction (buyruk)&#8217;dan olu\u015fan kimi komutlar atomik gibi g\u00f6r\u00fcnse de i\u00e7sel olarak yapt\u0131klar\u0131 birden fazla i\u015f s\u00f6z konusu oldu\u011funda atomik olamazlar. \u00d6rne\u011fin do\u011frudan bellek adresleri \u00fczerinde i\u015flem yapan artt\u0131rma, azaltma, ekleme, \u00e7\u0131karma, yer de\u011fi\u015ftirme komutlar\u0131 gibi. Bu komutlar\u0131n atomik olabilmesi i\u00e7in \u00f6zel olarak veriyolu (bus) kilitlenmelidir.<\/p>\n<p>Race condition problemimizin derinliklerine indi\u011fimizde meselenin atomicity konusunda indirgendi\u011fini g\u00f6rm\u00fc\u015f olmal\u0131s\u0131n\u0131z. E\u011fer yazd\u0131\u011f\u0131m\u0131z bir kod asl\u0131nda b\u00f6l\u00fcnebilir birka\u00e7 ad\u0131ma ayr\u0131labiliyorsa bir komut tamamlanmadan belli \u015fartlar olu\u015ftu\u011funda pek ala \u00e7al\u0131\u015fmas\u0131 kesilebilir. Yukar\u0131daki \u00f6rnek kodun neden eksik sayabilece\u011fine ili\u015fkin race condition durumunu bir grafik \u00fczerinde detayland\u0131ral\u0131m.<\/p>\n<p><a href=\"http:\/\/oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-357 size-full\" src=\"http:\/\/oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/1.png\" alt=\"\" width=\"834\" height=\"475\" srcset=\"https:\/\/www.oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/1.png 834w, https:\/\/www.oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/1-300x171.png 300w\" sizes=\"auto, (max-width: 834px) 100vw, 834px\" \/><\/a><\/p>\n<p>Yukar\u0131daki grafik iki farkl\u0131 CPU \u00fczerinde \u00e7al\u0131\u015fan e\u015f s\u00fcre\u00e7lerin bir kayna\u011fa eri\u015fim zamanlar\u0131n\u0131 g\u00f6stermektedir. Yukar\u0131da ad\u0131mlara b\u00f6ld\u00fc\u011f\u00fcm\u00fcz operasyonlar\u0131 grafi\u011fe d\u00f6kt\u00fc\u011f\u00fcm\u00fczde Race condition&#8217;\u0131n nas\u0131l olu\u015ftu\u011funu daha rahat kavrayabileceksiniz.<\/p>\n<p>Grafikte g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere iki farkl\u0131 CPU \u00fczerinde \u00e7al\u0131\u015fan e\u015f s\u00fcre\u00e7 bir kayna\u011fa (P) de\u011ferini i\u00e7sel yazmac\u0131na y\u00fcklemek amac\u0131yla eri\u015fmek istiyor. Burada CPU2 bu okuma iste\u011fini CPU1&#8217;den \u00f6nce ger\u00e7ekle\u015ftirdi\u011finde CPU2 veriyolunu sahiplenmi\u015f olur. Bu da bu e\u015f s\u00fcre\u00e7lerden bir di\u011ferini \u00e7al\u0131\u015ft\u0131ran CPU1&#8217;in komutunu di\u011ferine g\u00f6re geriye \u00f6telemesine sebep olmaktad\u0131r. CPU1 de bu bellek b\u00f6lgesini CPU2&#8217;den ge\u00e7 okudu\u011fundan sonraki komutlar da payla\u015f\u0131lan bellek b\u00f6lgesindeki verinin beklenmeyen bi\u00e7imde de\u011fi\u015fmesine sebep olacakt\u0131r. Ba\u015flang\u0131\u00e7 de\u011feri P=5 olan bu de\u011fi\u015fkenin s\u0131rayla t zamanda yap\u0131lan i\u015flemlerini ve her ad\u0131mdaki durumunu yazal\u0131m. Tabloyu okurken yukar\u0131daki grafi\u011fi referans olarak kullanman\u0131z yararl\u0131 olacakt\u0131r.<\/p>\n<p><a href=\"http:\/\/oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-355\" src=\"http:\/\/oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/2.png\" alt=\"2\" width=\"564\" height=\"122\" srcset=\"https:\/\/www.oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/2.png 564w, https:\/\/www.oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/2-300x65.png 300w\" sizes=\"auto, (max-width: 564px) 100vw, 564px\" \/><\/a><\/p>\n<p>Tabloda grafikte zaman dilimlerine b\u00f6l\u00fcnm\u00fc\u015f i\u015flem grafi\u011finin zaman dilimlerindeki register ve hedef de\u011fi\u015fken de\u011ferlerini g\u00f6stermektedir. Danan\u0131n kuyru\u011funun esas koptu\u011fu yer t+2 zaman dilimi. Dikkat ederseniz CPU2 yazmac\u0131ndaki de\u011feri artt\u0131r\u0131p geri hedef bellek b\u00f6lgesine bu de\u011feri yazm\u0131\u015f durumdad\u0131r. Ancak belle\u011fe yaz\u0131ld\u0131\u011f\u0131 anda hen\u00fcz CPU1 \u00f6nceden yazmac\u0131na ald\u0131\u011f\u0131 5 de\u011ferini yeni artt\u0131rm\u0131\u015ft\u0131r. Bu durumda CPU1&#8217;in sonraki komutu olan yazma\u00e7 de\u011ferinin bellek b\u00f6lgesine tekrar yaz\u0131lmas\u0131 sonucu yine belle\u011fe 6 de\u011feri yaz\u0131lacakt\u0131r. Halbuki senkron \u00e7al\u0131\u015fan 2 s\u00fcre\u00e7ten sonra 5 olan ba\u015flang\u0131\u00e7 de\u011feri 2 s\u00fcrecin \u00e7al\u0131\u015f\u0131p bitmesi sonucu P de\u011ferinin 7 olmas\u0131 gerekiyordu. \u0130\u015fte t+2 noktas\u0131 race condition&#8217;\u0131n kritik ger\u00e7ekle\u015fme noktas\u0131n\u0131 olu\u015fturmaktad\u0131r. Ve yinelemek gerekiyor ki bu i\u015flemler nanosaniyeler i\u00e7erisinde olup bitmektedir. Haliyle bu durum programc\u0131 a\u00e7\u0131s\u0131ndan tespit etmesi olduk\u00e7a zor bir i\u015ftir.<\/p>\n<p>Race condition&#8217;lar zamanlama ile alakl\u0131 \u015feyler olduklar\u0131ndan debug (hata ay\u0131klama) y\u00f6ntemleriyle tespit edilemezler. \u00c7\u00fcnk\u00fc debugging zaman maliyeti sebebiyle ba\u015fl\u0131 ba\u015f\u0131na race condition&#8217;\u0131 engelleyecek bir unsurdur. E\u011fer bir kodda race condition sebepli bir bozukluk zamanla g\u00f6zlenebiliyorsa bunu \u00e7\u00f6zmek kabul edelim ki zorlu bir s\u00fcre\u00e7 olacakt\u0131r. Hele ki yaz\u0131l\u0131m git gide b\u00fcy\u00fcm\u00fc\u015f, komplike bir hal alm\u0131\u015f durumda bir yaz\u0131l\u0131msa durum daha vahim hale gelir. Bu y\u00fczden programc\u0131 bu hataya d\u00fc\u015fmeden yaz\u0131l\u0131m\u0131n\u0131 gerekli kalitede kodlamak durumundad\u0131r. Ve yaz\u0131l\u0131m\u0131 thread-safe halde yazmaya harcad\u0131\u011f\u0131n\u0131z vakit, race condition olu\u015fmu\u015f yaz\u0131l\u0131m\u0131 d\u00fczeltmeye \u00e7al\u0131\u015fmaktan kat ve kat daha az olacakt\u0131r.<\/p>\n<h4><span style=\"color: #ff0000;\">Canl\u0131 Bir \u00d6rnek<\/span><\/h4>\n<p>Bu kadar teorik anlat\u0131mdan sonra sizin i\u00e7in race condition olu\u015fturan \u00e7al\u0131\u015fan bir \u00f6rnek g\u00f6stermek istiyorum. Bu i\u015f i\u00e7in ufak bir demo program\u0131 yazd\u0131m. \u00d6rnekleri bu program \u00fczerinden g\u00f6sterece\u011fim. Program\u0131n kaynak kodlar\u0131na <a href=\"https:\/\/gist.github.com\/0ffffffffh\/cf93ed82d86dffe8ddb8#file-rcdemo-c\">https:\/\/gist.github.com\/0ffffffffh\/cf93ed82d86dffe8ddb8#file-rcdemo-c<\/a> linkinden ula\u015fabilirsiniz. Program birden \u00e7ok senaryoyu test etmek i\u00e7in haz\u0131rland\u0131. Program basit\u00e7e payla\u015f\u0131ml\u0131 bir de\u011fi\u015fkeni birden fazla i\u015f par\u00e7ac\u0131\u011f\u0131 (thread) i\u00e7inde art\u0131rma \/ eksiltme i\u015flemi yap\u0131yor. Haricen a\u015fa\u011f\u0131daki opsiyonlardan g\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi bu thread&#8217;leri sistemdeki aktif i\u015flemci \u00e7ekirdeklerini e\u015fit \u015fekilde payla\u015ft\u0131rarak \u00e7al\u0131\u015ft\u0131rabiliyor, yahut sadece tek i\u015flemcili bir sistemi simule ederek \u00e7al\u0131\u015fabiliyor.<\/p>\n<p><a href=\"http:\/\/oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/31.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-363 size-full\" src=\"http:\/\/oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/31.png\" alt=\"\" width=\"677\" height=\"342\" srcset=\"https:\/\/www.oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/31.png 677w, https:\/\/www.oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/31-300x152.png 300w\" sizes=\"auto, (max-width: 677px) 100vw, 677px\" \/><\/a><\/p>\n<p>Program \u00e7e\u015fitli opsiyonlara sahip.<br \/>\n-w [N]: ka\u00e7 adet thread (i\u015f par\u00e7ac\u0131\u011f\u0131) kullan\u0131lacaksa N de\u011feri yerine thread adedi.<br \/>\n-i [N]: thread i\u00e7erisinde \u00e7al\u0131\u015fan art\u0131rma\/eksiltme iterasyonunun say\u0131s\u0131<br \/>\n-su: e\u011fer bu parametre verilirse program tek i\u015flemcili bir sistemi simule eder<br \/>\n-wa: Bu parametre say\u0131s\u0131 verilen thread&#8217;leri e\u015fit olarak bilgisayarda olan t\u00fcm \u00e7ekirdeklere payla\u015ft\u0131r\u0131r. Bu \u00e7al\u0131\u015fan kodun concurrent (E\u015fzamanl\u0131) \u00e7al\u0131\u015fmas\u0131n\u0131 garanti almak i\u00e7in kullan\u0131labilir<br \/>\n-tc: Verilen parametrelerle testin ka\u00e7 defa tekrar edilece\u011fini bildirir.<\/p>\n<p>Program\u0131n temel gayet basit. \u0130\u015fi esas yapan kod par\u00e7as\u0131 a\u015fa\u011f\u0131da bulunmaktad\u0131r. \u0130nceleyebilirsiniz. workerMethod i\u00e7erisindeki kod payla\u015f\u0131lan de\u011fi\u015fkeni art\u0131r\u0131p azaltma i\u015flemine tabi tutuyor. B\u00f6ylece bu de\u011ferin s\u0131f\u0131r olup olmama durumuna g\u00f6re bir race condition olu\u015fup olu\u015fmad\u0131\u011f\u0131na dair bilgi sahibi olaca\u011f\u0131z. \u0130sterseniz kod par\u00e7as\u0131n\u0131 ge\u00e7ebilirsiniz.<\/p>\n<pre class=\"line-height:18 lang:c decode:true\">LONG sharedValue = 0;\r\n\r\ntypedef struct _workerInfo\r\n{\r\n\tDWORD iteration;\r\n\tLONG *pShared;\r\n}workerInfo;\r\n\r\nDWORD WINAPI workerMethod(void *p)\r\n{\r\n\tworkerInfo *pWi = (workerInfo *)p;\r\n\r\n\tLONG *pVal = pWi-&gt;pShared;\r\n\tDWORD iteration = pWi-&gt;iteration;\r\n\r\n\twhile (iteration-- &gt; 0)\r\n\t{\r\n\t\t(*pVal)++;\r\n\t\t(*pVal)--;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\nvoid startWorkers(DWORD id,DWORD workerCount, DWORD iterationPerWorker, BOOL simulateUniprocessor, BOOL coreAffinity)\r\n{\r\n\tDWORD processorCount,affMask, processorId=0, dummy;\r\n\tworkerInfo wi;\r\n\tSYSTEM_INFO sysInfo;\r\n\tHANDLE *threads = NULL;\r\n\r\n\tGetSystemInfo(&amp;sysInfo);\r\n\r\n\tprocessorCount = simulateUniprocessor ? 1 : sysInfo.dwNumberOfProcessors;\r\n\r\n\tif (simulateUniprocessor &amp;&amp; !coreAffinity)\r\n\t\tcoreAffinity = TRUE;\r\n\r\n\tthreads = (HANDLE *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HANDLE) * workerCount);\r\n\r\n\twi.iteration = iterationPerWorker;\r\n\twi.pShared = &amp;sharedValue;\r\n\r\n\tif (!threads)\r\n\t{\r\n\t\tprintf(\"handle list could not allocated!\\n\");\r\n\t\treturn;\r\n\t}\r\n\r\n\tsharedValue = 0;\r\n\r\n\tprintf(\"\\n=== Test#%d is staring ===\\n\", id);\r\n\r\n\r\n\tfor (int i = 0; i &lt; workerCount;i++)\r\n\t{\r\n\t\tthreads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)workerMethod, &amp;wi, 0, &amp;dummy);\r\n\r\n\t\tif (coreAffinity)\r\n\t\t{\r\n\t\t\taffMask = 1 &lt;&lt; processorId;\r\n\r\n\t\t\tif (processorId == processorCount - 1)\r\n\t\t\t\tprocessorId = 0;\r\n\t\t\telse\r\n\t\t\t\tprocessorId++;\r\n\r\n\t\t\tSetThreadAffinityMask(threads[i], affMask);\r\n\t\t}\r\n\t}\r\n\r\n\tWaitForMultipleObjects(workerCount, (const HANDLE *)threads, TRUE, INFINITE);\r\n\r\n\tfor (int i = 0; i &lt; workerCount; i++)\r\n\t\tCloseHandle(threads[i]);\r\n\r\n\tHeapFree(GetProcessHeap(), 0, threads);\r\n\r\n\tprintf(\"=== Test#%d finished. Expected Value: 0, Actual sharedValue : %d ===\\n\\n\\n\",id, sharedValue);\r\n}<\/pre>\n<p>\u00d6ncelikle ufak bir testle ba\u015flayal\u0131m.<\/p>\n<p>Test#1) Program Opsiyonlar\u0131: <strong>-w 5 -i 50 -wa<\/strong><\/p>\n<pre class=\"lang:xhtml highlight:0 decode:true \">Test will be running using 5 Worker Threads with 50 iteration per worker.\r\nUniprocessor simulation is off, and Worker distribution is on\r\n\r\n\r\n=== Test#1 is staring ===\r\n=== Test#1 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n\r\nAll done<\/pre>\n<p>5 thread&#8217;in \u00e7al\u0131\u015ft\u0131\u011f\u0131 ve her birinde 50 iterasyonun \u00e7al\u0131\u015ft\u0131\u011f\u0131 1 adet testte herhangi bir race condition&#8217;a rastlamad\u0131k. En ba\u015fta da dedi\u011fim gibi race condition olu\u015fup olu\u015fmamas\u0131n\u0131 tahmin edemeyiz. \u0130lk \u00e7al\u0131\u015fmam\u0131zda herhangi bir race condition&#8217;a sebebiyet verecek durum olu\u015fmayacak kadar \u015fansl\u0131yd\u0131k. \u015eimdi biraz daha stresi artt\u0131ral\u0131m.<\/p>\n<p>Test#2) Program Opsiyonlar\u0131: <strong>-w 10 -i 500 -wa -tc 6<\/strong><\/p>\n<pre class=\"lang:xhtml highlight:0 decode:true\">Test will be running using 10 Worker Threads with 500 iteration per worker.\r\nUniprocessor simulation is off, and Worker distribution is on\r\n\r\n\r\n=== Test#1 is staring ===\r\n=== Test#1 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n\r\n=== Test#2 is staring ===\r\n=== Test#2 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n\r\n=== Test#3 is staring ===\r\n=== Test#3 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n\r\n=== Test#4 is staring ===\r\n=== Test#4 finished. Expected Value: 0, Actual sharedValue : 3 ===\r\n\r\n\r\n=== Test#5 is staring ===\r\n=== Test#5 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n\r\n=== Test#6 is staring ===\r\n=== Test#6 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n\r\nAll done<\/pre>\n<p>10 thread&#8217;li 500 iterasyonlu testi 6 defa yap\u0131lmas\u0131n\u0131 istedik. Bu defa \u00e7o\u011funluk olarak beklenen sonu\u00e7 alm\u0131\u015f olsak da 4 numaral\u0131 test sonucuna bakt\u0131\u011f\u0131m\u0131zda a\u00e7\u0131k bir \u015fekilde race condition olu\u015ftu\u011funu g\u00f6rebiliyoruz. \u0130terasyon s\u0131kl\u0131\u011f\u0131n\u0131 biraz daha artt\u0131ral\u0131m.<\/p>\n<p>Test#3) Program Opsiyonlar\u0131:<strong> -w 10 -i 2000 -wa -tc 6<\/strong><\/p>\n<pre class=\"lang:xhtml highlight:0 decode:true\">Test will be running using 10 Worker Threads with 2000 iteration per worker.\r\nUniprocessor simulation is off, and Worker distribution is on\r\n\r\n\r\n=== Test#1 is staring ===\r\n=== Test#1 finished. Expected Value: 0, Actual sharedValue : 30 ===\r\n\r\n=== Test#2 is staring ===\r\n=== Test#2 finished. Expected Value: 0, Actual sharedValue : 6 ===\r\n\r\n=== Test#3 is staring ===\r\n=== Test#3 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n=== Test#4 is staring ===\r\n=== Test#4 finished. Expected Value: 0, Actual sharedValue : 17 ===\r\n\r\n=== Test#5 is staring ===\r\n=== Test#5 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n=== Test#6 is staring ===\r\n=== Test#6 finished. Expected Value: 0, Actual sharedValue : 51 ===\r\n\r\nAll done<\/pre>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc gibi i\u015flem yo\u011funlu\u011fu artt\u0131k\u00e7a race condition olu\u015fma \u015fans\u0131 da o kadar art\u0131yor. \u00c7\u00fcnk\u00fc uzun s\u00fcre \u00e7al\u0131\u015fmakta olan birden fazla s\u00fcrecin e\u015f olmas\u0131 i\u00e7in daha fazla zaman tan\u0131m\u0131\u015f oluyoruz.<\/p>\n<h3><span style=\"color: #ff0000;\"><strong>Soru<\/strong><\/span><\/h3>\n<p>Peki madem bu sorun bir e\u015f zamanl\u0131l\u0131k problemi. E\u011fer \u00e7al\u0131\u015fan benzer bir kod uniprocessor (Tek i\u015flemci yahut \u00e7ekirdek) bir sistemde \u00e7al\u0131\u015fsayd\u0131 bu sorundan otomatik olarak kurtulmu\u015f olur muyduk? \u00c7\u00fcnk\u00fc ortada e\u015fzamanl\u0131 \u00e7al\u0131\u015fan herhangi ikincil bir i\u015flemci olmad\u0131\u011f\u0131ndan mant\u0131k olarak bunun olmamas\u0131 gerekir.<\/p>\n<p>Cevab\u0131 maalesef hay\u0131r. Uniprocessor bir sistemde \u00e7al\u0131\u015f\u0131yor olmam\u0131z bizi bu durumdan kurtaram\u0131yor. Peki bir i\u015flemci ile paralel \u00e7al\u0131\u015fan ikincil bir i\u015flemci olmad\u0131\u011f\u0131 halde bu durum nas\u0131l olu\u015fur? Bunun cevab\u0131 i\u015flemcinin kendisinde de\u011fil i\u015fletim sisteminin tasar\u0131m\u0131nda sakl\u0131d\u0131r. Yaz\u0131n\u0131n en ba\u015f\u0131nda bu konuya daha sonra de\u011finece\u011fimden bahsetmi\u015fim. \u0130\u015fte bu nokta bundan bahsetmek i\u00e7in uygun bir yer. Bunu anlamak i\u00e7in modern say\u0131labilecek i\u015fletim sistemlerinin sa\u011flad\u0131\u011f\u0131 multi-tasking, multi-threading gibi \u00f6zelliklerin temel de olsa anla\u015f\u0131labilmesi gerekir.<\/p>\n<p>\u0130\u015fletim sistemleri tekli i\u015flemcilerle de multi-threaded, multi-tasking \u00e7al\u0131\u015fabilme kapasitesine sahiplerdi. Bunu da i\u015flemciden ba\u011f\u0131ms\u0131z bir \u00e7ipin belli aral\u0131klarda bir interrupt (kesme) olu\u015fturmas\u0131yla sa\u011flamaktayd\u0131lar. Ho\u015f g\u00fcn\u00fcm\u00fczde de i\u015fler benzer \u015fekilde y\u00fcr\u00fcr ancak eskisi kadar ilkel de\u011fildir art\u0131k. Bu ba\u011f\u0131ms\u0131z ayg\u0131t (PIC) bir interrupt \u00fcretti\u011finde i\u015flemci \u00e7al\u0131\u015fmakta oldu\u011fu kodu durdurup interrupt handler rutinine dallan\u0131r. \u0130\u015fletim sistemi de bu handler k\u0131sm\u0131na kendi \u00f6zel kodlar\u0131n\u0131 yerle\u015ftirerek \u00e7al\u0131\u015fmay\u0131 bekleyen ba\u015fka bir thread&#8217;i listeden se\u00e7ip i\u015flemci \u00fczerine b\u0131rakarak \u00e7al\u0131\u015fmas\u0131n\u0131 sa\u011flamaktad\u0131r. Bu \u015fekilde bir d\u00f6ng\u00fc halinde tek i\u015flemci \u00fczerinde zaman payla\u015f\u0131ml\u0131 birden \u00e7ok i\u015f par\u00e7ac\u0131\u011f\u0131n\u0131 \u00e7al\u0131\u015ft\u0131rmak m\u00fcmk\u00fcn olmaktayd\u0131. Bu i\u015flem bizim alg\u0131layamayaca\u011f\u0131m\u0131z h\u0131zlarda yap\u0131ld\u0131\u011f\u0131ndan bizlerde bir\u00e7ok program ayn\u0131 anda \u00e7al\u0131\u015f\u0131yormu\u015f izlenimi olu\u015fturmaktad\u0131r. Halbuki olan her programa ait kodlar\u0131n s\u0131rayla \u00e7al\u0131\u015ft\u0131\u011f\u0131d\u0131r.<\/p>\n<p><a href=\"http:\/\/oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/4.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone  wp-image-371\" src=\"http:\/\/oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/4.png\" alt=\"4\" width=\"684\" height=\"438\" srcset=\"https:\/\/www.oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/4.png 842w, https:\/\/www.oguzkartal.net\/blog\/wp-content\/uploads\/2015\/11\/4-300x192.png 300w\" sizes=\"auto, (max-width: 684px) 100vw, 684px\" \/><\/a><\/p>\n<p>Yukar\u0131daki g\u00f6rsel bu i\u015flemin basit\u00e7e grafi\u011fe d\u00f6k\u00fclm\u00fc\u015f halidir. \u015eimdi belli aral\u0131klarla \u00e7al\u0131\u015fan kodlar kesilip yerlerine ba\u015fka kodlar \u00e7al\u0131\u015ft\u0131r\u0131labiliyorsa (Preemption) bu durum ayn\u0131 kodu \u00e7al\u0131\u015ft\u0131ran birden fazla Thread&#8217;in ba\u015fna da gelebilir gayet. Ancak ba\u015f\u0131m\u0131zda e\u015fzamanl\u0131 \u00e7al\u0131\u015fan bir donan\u0131m olmad\u0131\u011f\u0131ndan olu\u015fan durum e\u015fzamanl\u0131l\u0131k \u00e7ak\u0131\u015fmas\u0131ndan ziyade yanl\u0131\u015f yerde kesintiye u\u011frama tehlikesidir. Bu y\u00fczden race condition uniprocessor sistemlerde kolay olu\u015fmaz ancak kesinlikle olu\u015fmayaca\u011f\u0131n\u0131n garantisi de verilemez. En yukar\u0131daki \u00f6rne\u011fi Uniprocessor a\u00e7\u0131dan yorumlarsak<\/p>\n<pre class=\"lang:asm decode:true  \">Thread1:\r\nREG1 = [g_sharedValue]\r\n\/\\\/\\\/\\PREEMPTION\/\\\/\\\/\\\r\nREG1 = REG1 + 1\r\n[g_sharedValue} = REG1\r\n\r\nThread2:\r\nREG1 = [g_sharedValue]\r\nREG1 = REG1 + 1\r\n\/\\\/\\\/\\PREEMPTION\/\\\/\\\/\\\r\n[g_sharedValue} = REG1\r\n<\/pre>\n<p>Ayn\u0131 kodu \u00e7al\u0131\u015ft\u0131ran iki farkl\u0131 thread&#8217;in farkl\u0131 noktalarda kesilmesi kodun sonraki ad\u0131mlar\u0131nda yine istenmeyen sonu\u00e7lara sebebiyet verebilecektir.<\/p>\n<p>Bunu g\u00f6zlemlemek i\u00e7in demo program\u0131na tekrar d\u00f6nelim. Ayn\u0131 kodu tek \u00e7ekirdek \u00fczerinde \u00e7al\u0131\u015facak \u015fekilde zorlay\u0131p nas\u0131l \u015fartlar alt\u0131nda ne s\u0131kl\u0131kla race condition olu\u015fabilir inceleyelim.<\/p>\n<p>Testi ba\u015flang\u0131\u00e7 olarak \u00f6nceki multi-core versiyonda race condition&#8217;a sebebiyet veren senaryodan ba\u015flatal\u0131m.<\/p>\n<p>Test#1) Program Opsiyonlar\u0131: <strong>-w 10 -i 2000 -su -tc 5<\/strong><\/p>\n<pre class=\"lang:xhtml highlight:0 decode:true\">Test will be running using 10 Worker Threads with 2000 iteration per worker.\r\nUniprocessor simulation is on, and Worker distribution is off\r\n\r\n\r\n=== Test#1 is staring ===\r\n=== Test#1 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n=== Test#2 is staring ===\r\n=== Test#2 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n=== Test#3 is staring ===\r\n=== Test#3 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n=== Test#4 is staring ===\r\n=== Test#4 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n=== Test#5 is staring ===\r\n=== Test#5 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\nAll done<\/pre>\n<p>Test#2) Program Opsiyonlar\u0131:<strong> -w 150 -i 8000 -su -tc 5<\/strong><\/p>\n<pre class=\"lang:default highlight:0 decode:true\">Test will be running using 150 Worker Threads with 8000 iteration per worker.\r\nUniprocessor simulation is on, and Worker distribution is off\r\n\r\n\r\n=== Test#1 is staring ===\r\n=== Test#1 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n=== Test#2 is staring ===\r\n=== Test#2 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n=== Test#3 is staring ===\r\n=== Test#3 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n=== Test#4 is staring ===\r\n=== Test#4 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n=== Test#5 is staring ===\r\n=== Test#5 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\nAll done<\/pre>\n<p>Halen iyi g\u00f6r\u00fcn\u00fcyor. Peki ayn\u0131 komutu birka\u00e7 kez daha versek durum yine ayn\u0131 m\u0131 olacak? Ben farkl\u0131 bir sonu\u00e7 alana kadar birka\u00e7 kez daha ayn\u0131 komutu kulland\u0131m. \u00c7ok uzun s\u00fcrmedi 3. denememde farkl\u0131 bir sonu\u00e7 ald\u0131m.<\/p>\n<pre class=\"lang:default highlight:0 decode:true\">Test will be running using 150 Worker Threads with 8000 iteration per worker.\r\nUniprocessor simulation is on, and Worker distribution is off\r\n\r\n\r\n=== Test#1 is staring ===\r\n=== Test#1 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n=== Test#2 is staring ===\r\n=== Test#2 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\n=== Test#3 is staring ===\r\n=== Test#3 finished. Expected Value: 0, Actual sharedValue : 1 ===\r\n\r\n=== Test#4 is staring ===\r\n=== Test#4 finished. Expected Value: 0, Actual sharedValue : 1 ===\r\n\r\n=== Test#5 is staring ===\r\n=== Test#5 finished. Expected Value: 0, Actual sharedValue : 0 ===\r\n\r\nAll done<\/pre>\n<p>\u0130\u015fte \u015fanss\u0131z an\u0131m\u0131z. Tek \u00e7ekirdek \u00fczerinde istenmeyen sonu\u00e7 elde edebildik. \u015eanss\u0131zd\u0131k \u00e7\u00fcnk\u00fc yeteri kadar thread&#8217;i yeteri kadar s\u00fcre scheduler (zamanlay\u0131c\u0131) \u00fczerinde aktif olarak tuttuk. Art\u0131k \u00f6yle bir ana geldi ki scheduler o \u00e7ekirdek \u00fczerinde s\u0131kl\u0131kla prosesimize ait thread&#8217;leri zamanlamaya ba\u015flad\u0131 ve ayn\u0131 payla\u015f\u0131ml\u0131 kayna\u011fa ula\u015fmaya \u00e7al\u0131\u015fan d\u00fc\u015f\u00fck seviye operasyon da ayn\u0131 noktada yo\u011fun olarak bulundu\u011fundan beklenmeyen bir sonu\u00e7 ka\u00e7\u0131n\u0131lmaz oldu. Biz bu \u015fekilde sistemi biraz buna zorlad\u0131k. Buradaki ama\u00e7 bu problemin \u00f6nlem al\u0131nmad\u0131\u011f\u0131nda her \u015fekilde ortaya \u00e7\u0131kabilece\u011fiydi.<\/p>\n<p>Programc\u0131lar\u0131n g\u00f6revi ihtimaller ne kadar az olursa olsun bunlar\u0131 s\u0131f\u0131ra kesin bir \u015fekilde indirmek olmal\u0131d\u0131r. Bu tip sorunlar\u0131n \u00f6n\u00fcne ge\u00e7mek i\u00e7inse \u00e7e\u015fitli senkronizasyon ve kilit y\u00f6ntemleri kullan\u0131lmal\u0131d\u0131r. Bu yaz\u0131 yeterince uzun oldu\u011fundan e\u011fer k\u0131sa s\u00fcrede tekrar vakit bulabilirsem bu konunun devam\u0131 niteli\u011finde senkronizasyon ve kilit mekanizmalar\u0131 hakk\u0131nda bilgiler verip g\u00fcvenli \u015fekilde concurrent programlaman\u0131n ipu\u00e7lar\u0131n\u0131 bilgim dahilinde payla\u015fmaya \u00e7al\u0131\u015faca\u011f\u0131m.<\/p>\n<p>Zaman ay\u0131rd\u0131\u011f\u0131n\u0131z i\u00e7in te\u015fekk\u00fcrler.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Programlama ve programlama tekniklerinin geli\u015fimi, teknolojinin geli\u015fimiyle do\u011fru orant\u0131l\u0131 olarak de\u011fi\u015fim g\u00f6stermi\u015ftir. Kullan\u0131lan donan\u0131mlar daha g\u00fc\u00e7l\u00fc \u00f6zellikler sunduk\u00e7a bu onlar\u0131n tasar\u0131mlar\u0131n\u0131 da komplike bir hale getirmi\u015f ve bu donan\u0131mlar \u00fczerinde \u00e7al\u0131\u015fan yaz\u0131l\u0131mlar\u0131n da ona uygun \u015fekilde yeniden tasarlanmalar\u0131n\u0131 zorunlu k\u0131lm\u0131\u015ft\u0131r. \u00d6rne\u011fin bug\u00fcn multi-core yahut multi-processor (\u0130kisi aras\u0131nda fiziksel fark mevcuttur. Multiprocessor birden fazla fiziksel i\u015flemciyi&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"twitterCardType":"","cardImageID":0,"cardImage":"","cardTitle":"","cardDesc":"","cardImageAlt":"","cardPlayer":"","cardPlayerWidth":0,"cardPlayerHeight":0,"cardPlayerStream":"","cardPlayerCodec":"","footnotes":""},"categories":[64,49],"tags":[82,85,83,87,84,86],"class_list":["post-335","post","type-post","status-publish","format-standard","hentry","category-programming","category-security","tag-concurrency","tag-deadlock","tag-lock","tag-processor","tag-race-condition","tag-thread"],"_links":{"self":[{"href":"https:\/\/www.oguzkartal.net\/blog\/index.php\/wp-json\/wp\/v2\/posts\/335","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.oguzkartal.net\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.oguzkartal.net\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.oguzkartal.net\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.oguzkartal.net\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=335"}],"version-history":[{"count":43,"href":"https:\/\/www.oguzkartal.net\/blog\/index.php\/wp-json\/wp\/v2\/posts\/335\/revisions"}],"predecessor-version":[{"id":386,"href":"https:\/\/www.oguzkartal.net\/blog\/index.php\/wp-json\/wp\/v2\/posts\/335\/revisions\/386"}],"wp:attachment":[{"href":"https:\/\/www.oguzkartal.net\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=335"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.oguzkartal.net\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=335"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.oguzkartal.net\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=335"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}