Python'da Çoklu Okuma [Kodlama Örnekleriyle]

Yayınlanan: 2020-11-30

Kodu geliştirmek ve daha hızlı hale getirmek, temel Python bilgisi edinildikten sonraki adımdır. Multithreading, "Threads" kullanarak bu optimizasyonu gerçekleştirmenin yollarından biridir. Bu ipler nelerdir? Ve bunların süreçlerden farkı nedir? Hadi bulalım.

Bu eğitimin sonunda, aşağıdaki konularda bilgi sahibi olacaksınız:

  • Konular ve süreçler nelerdir?
  • Çoklu iş parçacığı nasıl elde edilir?
  • Sınırlamaları nelerdir?
  • Multithreading ne zaman kullanılır?

Dünyanın en iyi Üniversitelerinden çevrimiçi veri bilimi kurslarını öğrenin . Kariyerinizi hızlandırmak için Yönetici PG Programları, Gelişmiş Sertifika Programları veya Yüksek Lisans Programları kazanın.

İçindekiler

Python'daki Konular

Çoklu görev düşündüğümüzde, paralel yürütmeyi düşünüyoruz. Çoklu iş parçacığı kesinlikle paralel yürütme değil. Konular, programınızın bağımsız olarak çalışan farklı bölümlerinin yürütme akışının ayrı varlıkları olarak düşünülebilir. Temelde, iş parçacıkları paralel olarak yürütülmez, ancak Python bir iş parçacığından diğerine o kadar hızlı geçiş yapar ki, sanki paralelmiş gibi görünürler.

Öte yandan süreçler kesinlikle paraleldir ve daha hızlı yürütmeyi sağlamak için farklı çekirdeklerde çalışır. Konular farklı işlemcilerde de çalıştırılabilir, ancak yine de teknik olarak paralel olarak çalışmazlar.

Ve eğer threadler paralel olarak ilerlemezse, o zaman işleri nasıl daha hızlı hale getirirler diye mi düşünüyorsunuz? Cevap, işlemeyi her zaman daha hızlı hale getirmemeleridir. Çoklu iş parçacığı, özellikle iş parçacıklarının işlemeyi daha hızlı hale getireceği görevlerde kullanılır.

Bir iş parçacığının tüm bilgileri, İplik Kontrol Bloğunda (TCB) bulunur . TCB aşağıdaki ana bölümlerden oluşur:

  1. Benzersiz bir TID – Konu Tanımlayıcı
  2. İşlemdeki iş parçacığının yığınına işaret eden Yığın İşaretçisi
  3. İş parçacığı tarafından yürütülmekte olan talimatın adresini saklayan bir Program sayacı
  4. İş Parçacığının Durumu (çalışıyor, hazır, bekliyor, başlatılıyor veya tamamlandı)

Bunu söyledikten sonra, süreçler içinde kodu, verileri ve tüm dosyaları paylaşan birden fazla iş parçacığı içerebilir. Ve tüm iş parçacıklarının erişimleri olan kendi ayrı kayıtları ve yığınları vardır.

Şimdi, iş parçacıkları ortak verileri ve kodu kullanıyorsa, diğer iş parçacıklarını engellemeden hepsini nasıl kullanabileceklerini merak edebilirsiniz. Bu, bu eğitimde daha sonra bahsedeceğimiz Multithreading'in en büyük sınırlamasıdır.

Bağlam Değiştirme

Şimdi yukarıda açıklandığı gibi, iş parçacıkları paralel olarak değil, sonuç olarak çalışır. Böylece bir iş parçacığı T1 yürütmeye başladığında, diğer tüm iş parçacıkları bekleme modunda kalır. Yalnızca T1'in yürütülmesi tamamlandıktan sonra, kuyruğa alınmış diğer herhangi bir iş parçacığı yürütmeye başlayabilir. Python bir iş parçacığından diğerine o kadar hızlı geçer ki paralel yürütme gibi görünür. Bu anahtarlama, 'Bağlam Değiştirme' olarak adlandırdığımız şeydir.

çok iş parçacıklı programlama

Bir küp ve bir kare işlemi gerçekleştirmek için iş parçacıklarını kullanan aşağıdaki kodu göz önünde bulundurun.

içe aktarma iş parçacığı

def küp (n) :
print( “Küp: {}” .format(n * n * n))

def kare (n) :
print( “Kare: {}” .format(n * n))

eğer __name__ == “__main__” :
# ipliği oluştur
t1 = threading.Thread(hedef=kare, args=( 5 ,))
t2 = threading.Thread(target=cuber, args=( 5 ,))

# t1 dizisini başlat
t1.başlangıç()
# t2 dizisini başlat
t2.başlangıç()

# t1 tamamlanana kadar bekle
t1.join()
# t2 tamamlanana kadar bekleyin
t2.join()

# her iki iş parçacığı tamamlandı
print( “Bitti!” )

#Çıktı:
Kare: 25
Küp: 125
Tamamlandı!

Şimdi kodu anlamaya çalışalım.

İlk olarak, tüm görevlerden sorumlu olan Threading modülünü içe aktarıyoruz. Main içerisinde Thread sınıfının alt sınıflarını oluşturarak 2 tane thread oluşturuyoruz. Bu iş parçacığında yürütülmesi gereken işlev olan hedefi ve bu işlevlere iletilmesi gereken argümanları iletmemiz gerekiyor.

Şimdi threadler tanımlandıktan sonra onları başlatmamız gerekiyor. Bu, threadler üzerinde start metodunu çağırarak yapılır . Bir kez başlatıldığında, ana programın iş parçacıklarının işlenmesini bitirmesini beklemesi gerekir. Ana programın duraklamasına ve T1 ve T2 iş parçacıklarının yürütülmesini bitirmesini beklemesine izin vermek için wait yöntemini kullanırız.

Mutlaka Okuyun: Yeni Başlayanlar İçin Python Zorlukları

Konu Senkronizasyonu

Yukarıda tartıştığımız gibi, iş parçacıkları paralel olarak yürütülmez, bunun yerine Python birinden diğerine geçer. Bu nedenle, herhangi bir garip davranıştan kaçınmak için iş parçacıkları arasında doğru senkronizasyona çok kritik bir ihtiyaç vardır.

Yarış kondisyonu

Aynı işlem altındaki iş parçacıkları, birden çok iş parçacığı arasındaki veriler için bir "Yarış"a yol açabilecek ortak verileri ve dosyaları kullanır. Bu nedenle, bir veri parçasına birden fazla iş parçacığı tarafından erişilirse, hem iş parçacıkları tarafından değiştirilir hem de elde edeceğimiz sonuçlar beklendiği gibi olmaz. Buna Yarış Koşulu denir.

Dolayısıyla, aynı verilere erişimi olan iki iş parçacığınız varsa, o iş parçacığı yürütülürken her ikisi de ona erişebilir ve bunları değiştirebilir. Bu nedenle, T1 yürütmeye başladığında ve bazı verileri değiştirdiğinde, T2 uyku/bekleme modundadır. Ardından T1 yürütmeyi durdurur ve kontrolü aynı verilere erişimi olan T2'ye vererek uyku moduna geçer. Böylece T2 şimdi aynı verileri değiştirecek ve üzerine yazacak ve bu da T1 yeniden başladığında sorunlara yol açacaktır.

İplik Senkronizasyonunun amacı, bu Yarış Durumunun asla gelmemesini ve şifrenin kritik bölümüne iş parçacıkları tarafından senkronize bir şekilde birer birer erişilmesini sağlamaktır.

kilitler

Yarış Durumunu ve sonuçlarını çözmek ve önlemek için iş parçacığı modülü, iş parçacıklarının senkronizasyonuna yardımcı olmak için Semaforları kullanan bir Kilit sınıfı sunar. Semaforlar ikili bayraklardan başka bir şey değildir. Bunları, “Etkileşimli” (1'e eşdeğer) veya “Etkileşimli değil” (0'a eşdeğer) değerine sahip Telefon kulübelerinde “Nişanlı” işareti olarak kabul edin. Bu nedenle, bir iş parçacığı kilitli bir kod parçasıyla her karşılaştığında, kilidin zaten 1 durumunda olup olmadığını kontrol etmesi gerekir. Eğer öyleyse, kullanabilmesi için 0 olana kadar beklemesi gerekecek.

Lock sınıfının iki birincil yöntemi vardır:

  1. gain([blocking]) : Elde etme yöntemi, parametre engellemeyi True veya False olarak alır . T1 iş parçacığı için bir kilit, True olarak engelleme ile başlatıldıysa, kodun kritik bölümü başka bir T2 iş parçacığı tarafından kilitlenene kadar bekleyecek veya engellenmiş olarak kalacaktır. Diğer T2 iş parçacığı kilidi serbest bıraktığında, T1 iş parçacığı kilidi alır ve True değerini döndürür .

Öte yandan, T1 iş parçacığı için kilit False olarak parametre engelleme ile başlatılmışsa , kritik bölüm zaten T2 iş parçacığı tarafından kilitlenmişse, T1 iş parçacığı beklemez veya bloke olarak kalır. Kilitli olarak görürse, hemen False döndürür ve çıkar. Ancak, kod başka bir iş parçacığı tarafından kilitlenmemişse, kilidi alır ve True değerini döndürür .

release() : Kilit üzerinde serbest bırakma yöntemi çağrıldığında kilidin kilidini açar ve True değerini döndürür. Ayrıca, kilidin açılmasını bekleyen herhangi bir iş parçacığı olup olmadığını kontrol edecektir. Varsa, tam olarak bunlardan birinin kilide erişmesine izin verecektir.

Ancak, kilit zaten açılmışsa, bir ThreadError ortaya çıkar.

kilitlenmeler

Birden fazla kilitle uğraştığımızda ortaya çıkan bir diğer sorun da – Kilitlenmeler. Kilitlenmeler, çeşitli nedenlerle kilitler iş parçacığı tarafından serbest bırakılmadığında meydana gelir. Aşağıdakileri yaptığımız basit bir örneği ele alalım:

içe aktarma iş parçacığı

l = iş parçacığı.Kilit()
# 1. edinmeden önce
l.almak()
# 2. edinmeden önce
l.almak()
# Şimdi kilidi iki kez aldı

Yukarıdaki kodda, elde etme yöntemini iki kez çağırıyoruz, ancak ilk kez edinildikten sonra bırakmıyoruz. Bu nedenle, Python ikinci edinme ifadesini gördüğünde, önceki kilidi hiç serbest bırakmadığımız için süresiz olarak bekleme moduna geçecektir.

Bu kilitlenme koşulları, siz farkında olmadan kodunuza sızabilir. Bir serbest bırakma çağrısı ekleseniz bile, kodunuz yarı yolda başarısız olabilir ve serbest bırakma asla aranmaz ve kilit kilitli kalır. Bunun üstesinden gelmenin bir yolu , Bağlam Yöneticileri olarak da adlandırılan with as ifadesini kullanmaktır. with as ifadesi kullanıldığında , işlem bittiğinde veya herhangi bir nedenle başarısız olduğunda kilit otomatik olarak serbest bırakılır.

Okuyun: Python Proje Fikirleri ve Konuları

Gitmeden önce

Daha önce tartıştığımız gibi, Multithreading, her şeyi paralel olarak çalıştırmadığı için tüm uygulamalarda kullanışlı değildir. Ancak Multithreading'in ana uygulaması, verilerin yüklenmesini beklerken CPU'nun boşta oturduğu G/Ç görevleri sırasındadır. CPU'nun bu boşta kalma süresi diğer görevlerde kullanıldığından çoklu iş parçacığı burada çok önemli bir rol oynar ve böylece optimizasyon için ideal hale gelir.

Veri bilimi hakkında bilgi edinmek istiyorsanız, IIIT -B & upGrad'ın çalışan profesyoneller için oluşturulmuş ve 10'dan fazla vaka çalışması ve proje, uygulamalı uygulamalı atölye çalışmaları, endüstri uzmanlarıyla mentorluk, 1 Endüstri danışmanlarıyla bire bir, en iyi firmalarla 400+ saat öğrenim ve iş yardımı.

Python'da bir iş parçacığı nedir?

Konular, Python'da yürütülmek üzere programlanabilecek bir süreç içindeki varlıklardır. Layman'ın terimleriyle, bir iş parçacığı, bir bilgisayar tarafından gerçekleştirilen bir hesaplama işlemidir. Bir program içinde, geliştiricilerin diğer komut dosyalarından bağımsız olarak çalıştırabileceği bir dizi talimattır. İş parçacıkları, paralellik kullanarak uygulama hızını artırmanıza olanak tanır. Görevlerin paralel olarak çalışmasını sağlayacak hafif bir süreçtir. İş parçacıkları bağımsız olarak çalışır ve CPU kullanımını en üst düzeye çıkararak CPU performansını artırır.

Python'da çoklu iş parçacığının kullanımı nedir?

Çoklu iş parçacığı, Python programlamasında, bir CPU yardımıyla iş parçacıkları arasında hızlı geçiş yaparak (bağlam değiştirme olarak adlandırılır) birçok iş parçacığının aynı anda çalışmasına izin veren bir iş parçacığı oluşturma tekniğidir. Görevimizi birden çok ayrı bölüme ayırabileceğimizde, çoklu iş parçacığını kullanırız. Örneğin, verileri almak ve bu sorguyu çok sayıda bireysel sorguya bölmek için karmaşık bir veritabanı sorgusu yürütmeniz gerektiğini varsayalım. Bu durumda, her sorguya bir iş parçacığı tahsis etmek ve hepsini paralel olarak çalıştırmak tercih edilecektir.

İş parçacığı senkronizasyonu nedir?

İş parçacığı senkronizasyonu, iki veya daha fazla eşzamanlı işlemin veya iş parçacığının, bir programın önemli bir parçasını aynı anda yürütmemesini garanti eden bir yöntem olarak tanımlanır. Senkronizasyon yöntemleri, süreçlerin önemli bölümlere erişimini kontrol etmek için kullanılır. Bir program içinde iki veya daha fazla iş parçacığı başlattığımızda, birkaç iş parçacığının aynı kaynağa erişmeye çalışması ve eşzamanlılık zorlukları nedeniyle beklenmedik sonuçlara yol açması ihtimali vardır. Örneğin, birçok iş parçacığı aynı dosyaya yazmaya çalışırsa, iş parçacıklarından biri verileri geçersiz kılabileceğinden veya bir iş parçacığı açılırken başka bir iş parçacığı aynı dosyayı kapattığından veriler bozulabilir.