WEBVTT

00:05.350 --> 00:09.730
Şimdi veri kilitleme olarak adlandırılan diğer kilitleme türünü tartışıyoruz.

00:09.730 --> 00:10.480
Doğru.

00:10.780 --> 00:15.130
Veri kilitlemeyi anlamak için, burada bir foo fonksiyonu olduğunu görebilirsiniz.

00:15.130 --> 00:21.310
Ve bu foo fonksiyonunda, bir liste nesnesi üzerinde bazı işlemler gerçekleştirdiğimiz

00:21.310 --> 00:24.190
kodun bir kısmı var, doğru.

00:24.220 --> 00:29.560
Bu, öğrencilerin bir bağlantı listesi olabilir, çalışanların bir bağlantı listesi olabilir veya uygulamanızın

00:29.560 --> 00:33.040
koruduğu herhangi bir nesne türünün bir bağlantı listesi olabilir.

00:33.040 --> 00:33.730
Doğru.

00:33.760 --> 00:38.770
Bu kritik bir bölüm çünkü bu liste nesnesi üzerinde bazı işlemler gerçekleştiriyoruz.

00:38.800 --> 00:45.220
İşleminizde çalışan birkaç iş parçacığı olabileceğini ve birkaç iş parçacığının kodun çeşitli bölümlerinde bu liste

00:45.220 --> 00:49.300
nesnesi üzerinde belirli işlemler gerçekleştirebileceğini düşünün.

00:49.330 --> 00:49.990
Doğru.

00:50.020 --> 00:52.450
Yani bu işlem herhangi bir şey olabilir.

00:52.450 --> 00:54.520
Bağlantı listesine bir düğüm ekliyor olabilir.

00:54.550 --> 00:58.330
Bir düğümü arıyor olabilir, bir düğümü siliyor olabilir ya da herhangi bir şey olabilir.

00:58.330 --> 00:58.990
Değil mi?

00:59.820 --> 01:06.450
Dolayısıyla kodun bu kısmı kritik bir bölümdür çünkü kodun diğer kısımlarında programın diğer

01:06.450 --> 01:11.400
iş parçacıkları tarafından erişilen nesneye erişmeye çalışıyoruz.

01:11.400 --> 01:15.780
Şu anda bu kritik bir bölüm olduğu için bunu görebilirsiniz.

01:15.780 --> 01:23.340
Bu yüzden hiç düşünmeden, bu kritik bölümü muteksler kullanarak korumamız gerekir.

01:23.340 --> 01:31.230
Bu yüzden bu kritik bölümü yine p thread mutex lock ve p thread mutex unlock API çağrıları arasına sıkıştıracağız.

01:31.230 --> 01:32.010
Doğru.

01:32.130 --> 01:40.410
Şimdi burada dikkat edilmesi gereken nokta, burada günlüğe kaydedilen ve günlüğü açılan muteksin liste nesnesinin

01:40.410 --> 01:42.540
bir özelliği olduğudur.

01:42.900 --> 01:48.690
Burada mutex nesnesi, üzerinde işlem yapılan veri yapısına aittir.

01:48.690 --> 01:49.350
Doğru.

01:51.910 --> 01:59.230
Böylece her veri yapısının kendi muteksiyle ilişkilendirildiğini ve bu muteksin bir koruma görevi gördüğünü

01:59.230 --> 02:00.550
görebilirsiniz.

02:01.060 --> 02:08.140
Böyle bir muteks, veri yapısını eş zamanlı iş parçacığından, sürecin birkaç iş parçacığı tarafından güvenli olmayan erişimden

02:08.140 --> 02:09.190
korur.

02:09.980 --> 02:14.110
Öyleyse bir örnek yardımıyla veri kaydını anlamaya çalışalım.

02:14.120 --> 02:19.550
Diyelim ki uygulamanızda bir fonksiyon var ve bu fonksiyonun amacı

02:19.550 --> 02:26.300
sadece a a olabilir değerine bağlı olarak listeden belirli bir düğümü aramak.

02:26.300 --> 02:33.170
Bunun bir çalışanın çalışan kimliği olduğunu varsayalım veya ne tür bir liste geçirdiğinize bağlı olarak

02:33.200 --> 02:36.040
öğrencinin rulo numarası olabilir.

02:36.050 --> 02:40.400
Bu, çalışanların bağlı listesi veya öğrencilerin bağlı listesi olabilir.

02:40.400 --> 02:41.090
Değil mi?

02:41.090 --> 02:44.990
Böylece düğümü bağlı listeden kaldırırız ve sonra düğümü serbest bırakırız.

02:45.740 --> 02:48.140
Şimdi birinci senaryoyu düşünün.

02:48.170 --> 02:55.610
Birinci senaryo, listeden düğüm silmek olan bu özel API'yi çağıran bir T1 iş parçacığı olduğu ve aktarılan

02:55.610 --> 03:00.890
liste nesnesinin bağlantılı bir öğrenci listesi olduğu anlamına gelir.

03:02.030 --> 03:02.720
Doğru.

03:03.550 --> 03:07.360
Ve A değerinin 25 olarak ayrıştırıldığını varsayalım.

03:07.510 --> 03:14.440
Yani bu basitçe, 31'in bağlantı listesinden kural numarası örneğin 25 olan bir öğrenci kaydını silmeye çalıştığı

03:14.440 --> 03:16.150
anlamına gelir.

03:16.180 --> 03:17.620
Bu sadece bir örnek.

03:19.930 --> 03:25.300
Ve bu API'yi çağıran başka bir konu da var.

03:25.450 --> 03:26.080
Doğru.

03:26.080 --> 03:32.560
Ve t bir ve t iki eşzamanlı bir şekilde yürütülmeye çalışıldı ve t iki iş parçacığının bu API'ye

03:32.560 --> 03:37.600
aktardığı liste nesnesi, örneğin çalışanların bir listesidir.

03:38.250 --> 03:38.910
Doğru.

03:39.090 --> 03:44.670
Ve a değeri, diyelim ki bir çalışan kimliği olan 30'u temsil eder.

03:46.030 --> 03:54.370
Böylece aynı kod parçasının T1 ve T2 iş parçacığı tarafından çağrıldığını, ancak T1 ve T2 iş parçacıklarının aslında farklı

03:54.400 --> 03:58.760
liste nesneleri üzerinde işlem yaptığını görebilirsiniz.

03:58.780 --> 04:01.400
Bu tamamen farklı veri yapılarıdır.

04:01.420 --> 04:02.200
Doğru.

04:02.440 --> 04:09.400
Dolayısıyla, T1 ve T2 iş parçacığı aynı kod parçasını çağırdığı sürece, ancak bu kod parçası tamamen

04:09.400 --> 04:17.320
farklı nesneler üzerinde hareket ediyorsa, o zaman söz konusu kod T1 ve T2 iş parçacığı için kritik bir bölüm

04:17.320 --> 04:18.670
değildir.

04:18.790 --> 04:19.570
Doğru.

04:20.980 --> 04:29.650
Bu durumda T1 ve T2 iş parçacıklarının eşzamanlı erişimi herhangi bir değişmezlik sorununa yol açmayacaktır.

04:30.770 --> 04:36.410
Bunun nedeni T1 ve T2 iş parçacığının tamamen farklı nesneler üzerinde hareket ediyor olmasıdır.

04:37.360 --> 04:37.810
Dene.

04:37.850 --> 04:43.930
T1, öğrencilerin bağlantı listesinden bir düğümü silmeye çalışırken, T2 iş parçacığı çalışanların bağlantı listesinden

04:43.960 --> 04:46.360
bir düğümü silmeye çalışmaktadır.

04:48.300 --> 04:53.610
Yani burada sadece bir geliştirici veya programcı olarak koda bakarak, bu belirli kod parçasının

04:53.610 --> 04:56.580
kritik bir bölüm olup olmadığını anlayamazsınız.

04:57.470 --> 05:00.110
Ama şimdi başka bir senaryoyu ele alalım.

05:01.480 --> 05:07.780
Şimdi ikinci senaryoda, bir numaralı tehdidin bu API'yi çağırdığını ve geçirdiği listenin bir öğrenci

05:07.780 --> 05:10.960
listesi olduğunu varsayalım, değil mi?

05:10.960 --> 05:17.590
Ve sıra numarası 25 olan bir öğrenci için bağlantı listesinden bir düğümü silmeye çalışıyor.

05:17.920 --> 05:18.760
Doğru.

05:19.240 --> 05:25.990
Benzer şekilde, aynı API ve iş parçacığı olan bu API'yi çağıran bir T iki iş parçacığımız var.

05:25.990 --> 05:30.310
T2 yine aynı öğrenci bağlantı listesi üzerinde hareket etmektedir.

05:30.310 --> 05:31.030
Doğru.

05:31.630 --> 05:37.150
Ve diyelim ki t iki numaralı iş parçacığı bağlantı listesinden rulo numarası 30 olan bir düğümü silmeye

05:37.150 --> 05:37.870
çalışıyor.

05:38.050 --> 05:38.850
Doğru.

05:38.860 --> 05:40.900
Burada o konuyu görebilirsiniz.

05:40.930 --> 05:46.480
Bu durumda T1 ve t2 iş parçacığı aynı bağlantı listesi üzerinde hareket etmektedir.

05:46.480 --> 05:47.230
Doğru.

05:50.270 --> 05:56.810
T bir ve T iki aynı nesneler üzerinde hareket ettiği sürece, yani her ikisi de aynı nesneden bir düğüm silmeye

05:56.810 --> 05:58.520
çalıştığı sürece.

05:58.520 --> 06:02.510
Bu, bu kod parçasının artık kritik bir bölüm olarak davrandığı anlamına gelir.

06:04.160 --> 06:10.580
T1 ve T2 iş parçacığının eş zamanlı erişimi bu durumda değişmezlik sorununa neden olacaktır.

06:10.610 --> 06:17.390
Bunun nedeni, hem T1 hem de T2 iş parçacığının aynı nesne üzerinde yazma işlemi gerçekleştiriyor olmasıdır, bu da aynı

06:17.390 --> 06:19.640
bağlantı listesi yazma işlemidir.

06:22.250 --> 06:26.040
Şimdi birinci senaryo ile ikinci senaryo arasındaki farkı anladınız.

06:26.060 --> 06:32.360
Birinci senaryoda, T1 tehdidi ve T2 tehdidi farklı liste nesneleri üzerinde hareket ediyordu ve bu nedenle

06:32.360 --> 06:34.970
bu kod parçası kritik bir bölüm değildi.

06:34.970 --> 06:41.450
Ancak ikinci senaryoda, her iki tehdit de aynı liste nesnesi üzerinde hareket eder ve bu nedenle bu kod parçası

06:41.450 --> 06:43.070
kritik bölüm haline gelir.

06:43.070 --> 06:43.790
Değil mi?

06:44.540 --> 06:50.240
Dolayısıyla, sadece koda bakarak bir kod parçasının kritik

06:50.240 --> 06:54.750
bir bölüm olup olmadığına karar veremezsiniz.

06:54.770 --> 07:00.920
Bu kod parçasına erişen eşzamanlı iş parçacıklarının aslında aynı nesneler üzerinde mi yoksa farklı nesneler

07:00.920 --> 07:04.040
üzerinde mi hareket ettiğini bilmek de önemlidir.

07:04.040 --> 07:04.670
Doğru.

07:06.790 --> 07:08.620
Yani bu örneği ele alalım.

07:08.620 --> 07:12.370
Eğer kod kilitleme uyguluyorsanız, o zaman sorun ne olabilir?

07:14.320 --> 07:20.200
Şimdilik, bu kodu kod kilitleme özelliğini kullanacak şekilde güncellediğimi görebilirsiniz.

07:20.320 --> 07:26.890
Bir dosyada global bir mutex nesnesi bildirdim ve potansiyel kritik bölüm kodunu Pthread

07:26.890 --> 07:32.160
mutex lock ve pthread mutex unlock API çağrıları arasına sıkıştırdım.

07:32.170 --> 07:32.830
Doğru.

07:32.830 --> 07:35.850
Bu yüzden bu örnekte yine kod kilitlemeyi kullanıyorum.

07:35.860 --> 07:37.960
Şimdi buradaki sorunu görebilirsiniz.

07:39.480 --> 07:41.250
Şimdi burada bir vaka düşünün.

07:41.250 --> 07:47.340
T1 iş parçacığı ve T2 iş parçacığı aynı bağlantı listesi üzerinde hareket ederken, bir öğrencinin bağlantı listesi

07:47.340 --> 07:48.300
diyelim.

07:48.420 --> 07:49.200
Değil mi?

07:51.570 --> 07:56.850
Böylece 31 bu belirli işlevi çalıştırdığında muteksi kilitleyecektir.

07:56.850 --> 08:01.980
Şu anda muteksin T1 iş parçacığı tarafından kilitlenmiş olması.

08:02.010 --> 08:08.730
Eğer t2 iş parçacığı bu API'yi çağırmaya çalışırsa, t2 iş parçacığı bu belirli satırda engellenecektir.

08:08.730 --> 08:09.510
Doğru.

08:11.320 --> 08:18.160
Şimdi T1 ve T2 iş parçacıklarının farklı liste nesneleri üzerinde çalıştığı bir senaryo düşünün.

08:18.280 --> 08:23.020
T1 iş parçacığının öğrenci listesi ve iş parçacığı üzerinde hareket ettiğini varsayalım.

08:23.050 --> 08:26.440
T2 çalışan listesine göre hareket etmektedir.

08:26.620 --> 08:27.400
Doğru.

08:27.400 --> 08:34.660
Ve her iki iş parçacığı da eşzamanlı olarak her iki bağlı listeden ilgili belirli bir düğümü silmek için bu özel

08:34.660 --> 08:35.920
API'yi çağırır.

08:35.950 --> 08:36.580
Doğru.

08:37.480 --> 08:43.810
Şimdi t1 iş parçacığının bu API'yi çağırdığını ve t1 iş parçacığının bu belirli global muteksi kilitleyeceğini

08:43.810 --> 08:44.860
varsayalım.

08:44.860 --> 08:45.580
Doğru.

08:47.670 --> 08:50.930
Ve hatta tehdit işini yapmaya devam ediyor.

08:50.940 --> 08:56.910
Yani, bu noktada T1 tehdidi kritik bölümde yürütülürken,

08:56.910 --> 09:03.210
diyelim ki T2 tehdidi de geldi ve bu API'yi çağırdı, değil mi?

09:03.210 --> 09:08.190
Ve şimdi T2 tehdidi bu belirli global muteksin zaten kilitli olduğunu görecektir.

09:08.220 --> 09:11.760
Bu da T2 tehdidinin talimatlarda engelleneceği anlamına gelir.

09:11.760 --> 09:13.320
I5 sağda.

09:14.760 --> 09:18.840
Yani bu, iki numaralı ipliğin burada bloke olacağı anlamına geliyor.

09:19.320 --> 09:20.040
Değil mi?

09:20.070 --> 09:22.560
İki numaralı iplik engellenecektir.

09:25.370 --> 09:30.230
Ve T1 tehdidi kritik bölüm üzerinden yürütülmesini tamamlamadığı sürece.

09:30.230 --> 09:37.130
Ve son olarak, T1 iş parçacığı muteksi serbest bıraktığında, kritik bölüme yalnızca T2 iş parçacığı girer.

09:37.670 --> 09:45.290
Ancak şimdi burada ortaya çıkan basit bir soru, iki iş parçacığı çakışmayan işlemler gerçekleştirirken

09:45.290 --> 09:50.370
neden kritik bölümü seri olarak yürütmek zorunda olduğunuzdur?

09:50.390 --> 09:56.360
İki iş parçacığı çakışmayan işlemler gerçekleştiriyor çünkü iki iş parçacığı aslında farklı veri yapıları

09:56.360 --> 09:58.640
üzerinde birlikte hareket ediyor.

09:58.640 --> 09:59.420
Değil mi?

10:00.670 --> 10:06.850
Bir iş parçacığının gereksiz yere başka bir iş parçacığını engellemesini istemezsiniz ve bundan hiçbir şey kazanmazsınız.

10:06.880 --> 10:07.540
Değil mi?

10:08.650 --> 10:15.070
Dolayısıyla bu örnekte, kod kilitlemenin aslında muteksleri kullanmanın doğru bir yolu olmadığını görebilirsiniz.

10:15.850 --> 10:20.310
Burada muteksleri koda göre kullanmak, kilitleme hiç mantıklı değil.

10:20.320 --> 10:26.920
Bu nedenle, burada muteksi kod kilitlemesine göre kullanmanın neden bir yol olmadığını açıkladıktan sonra.

10:26.950 --> 10:30.270
Veri kilitlemenin ortaya çıkmasının nedeni budur.

10:30.280 --> 10:31.660
Şuna bir bakalım.

10:31.660 --> 10:38.770
Veri kilitlemenin aslında muteksleri kullanmanın doğru bir yolu olduğu ve bu örnekte karşılıklı dışlama sağladığı.

10:41.010 --> 10:47.790
Veri günlüğü tutarken, programınızın kodunun bir kısmını günlüğe kaydetmek yerine veri yapısını günlüğe kaydetmeye

10:47.790 --> 10:49.260
odaklanıyoruz.

10:49.260 --> 10:50.040
Doğru.

10:50.550 --> 10:58.320
Dolayısıyla nihai hedefimiz, bu API'nin T1 ve T2 tehditleri tarafından her iki iş parçacığı da aynı bağlantı listesini, diyelim

10:58.320 --> 11:04.680
ki öğrencilerin bağlantı listesini güncelleyecek şekilde çağrılması durumunda, bu iş parçacıklarından

11:05.160 --> 11:10.140
yalnızca birinin kritik bölüme girmesine izin verilmesi olmalıdır.

11:10.140 --> 11:10.850
Değil mi?

11:10.860 --> 11:16.260
Yani, T1 iş parçacığı kritik bölüme girerse, t2 iş parçacığı engellenmelidir ve bunun tersi

11:16.260 --> 11:17.250
de geçerlidir.

11:17.400 --> 11:24.900
Ancak başka bir senaryoda, aynı API T1 ve T2 iş parçacığı tarafından çağrılıyorsa, T1 iş parçacığı bir öğrenci bağlantı

11:24.900 --> 11:32.460
listesi üzerinde ve T2 iş parçacığı da bir çalışan bağlantı listesi üzerinde çalışıyorsa, her iki iş parçacığının

11:33.000 --> 11:37.920
da birbirini engellemeden çalışmasına izin verilmelidir.

11:37.920 --> 11:41.500
Bu durumda ilk etapta kritik bir bölüm bulunmamaktadır.

11:41.890 --> 11:42.700
Doğru.

11:44.110 --> 11:51.370
Yani yapacağım şey, bu özel kod parçasını p thread, mutex lock ve p thread mutex unlock

11:51.400 --> 11:55.540
API çağrıları arasında sandviçleyeceğim.

11:55.570 --> 12:01.180
Buradaki tek fark, kilitleme ve kilit açma için kullanılan mutex nesnesinin, üzerinde

12:01.210 --> 12:06.700
işlem yapılan veri yapısının sahip olduğu bir mutex nesnesi olmasıdır.

12:06.700 --> 12:07.510
Doğru.

12:07.990 --> 12:12.820
Burada mutex nesnesinin liste nesnesinin veri üyelerinden biri olduğunu görebilirsiniz.

12:12.850 --> 12:13.540
Doğru.

12:15.880 --> 12:22.630
Bu da basitçe T1 ve T2 iş parçacıklarının birbirlerini engelleyeceği ve kritik bölümde yalnızca bir iş parçacığının

12:22.630 --> 12:24.670
çalışacağı anlamına gelir.

12:25.240 --> 12:29.990
Yalnızca T1 ve T2 iş parçacığı aynı bağlantı listesinde hareket ettiğinde.

12:30.020 --> 12:30.700
Doğru.

12:32.380 --> 12:38.980
Ancak T1 ve T2 iş parçacığı farklı bağlı listeler üzerinde çalışıyorsa, T1 ve T2 iş parçacıklarının

12:38.980 --> 12:43.050
her ikisi de farklı muteksleri kilitleyecektir.

12:43.060 --> 12:46.480
Doğru, çünkü liste nesnesinin kendisi farklıdır.

12:47.020 --> 12:56.560
Yani bu durumda T1 ve T2 kodun bu belirli parçasını eşzamanlı veya aynı anda yürütebilir.

12:56.560 --> 12:57.250
Doğru.

12:59.530 --> 13:07.630
Bu durumda, hem T1 hem de T2 iş parçacığı, üzerinde hareket ettikleri ilgili bağlı listeden bir düğümü gerçekten

13:07.630 --> 13:10.030
arayabilir ve kaldırabilir.

13:10.030 --> 13:10.720
Doğru.

13:11.590 --> 13:17.140
Dolayısıyla, kritik bölümleri korumak için Mutex'leri kullandığınız çok iş parçacıklı programlar

13:17.170 --> 13:22.840
yazarken, vakaların %90'ında kod kilitleme yerine veri kilitlemeyi kullanacaksınız.

13:23.260 --> 13:29.800
Çoğu zaman Mutex'leri programınızın bir kod parçasını korumak yerine iş parçacıkları arasında paylaşılan verileri

13:29.800 --> 13:31.510
korumak için kullanırız.
