Python programlama dili, çoklu işlemeyi veya çoklu okumayı kullanmanıza izin verir.Bu eğitimde, Python'da çok iş parçacıklı uygulamaların nasıl yazılacağını öğreneceksiniz.
Konu nedir?
Bir iş parçacığı, eşzamanlı programlamada bir uygulama birimidir. Çoklu okuma, bir CPU'nun aynı anda bir işlemin birçok görevini yürütmesine izin veren bir tekniktir. Bu iş parçacıkları, süreç kaynaklarını paylaşırken ayrı ayrı çalıştırılabilir.
Süreç nedir?
Süreç temelde yürütülen programdır. Bilgisayarınızda bir uygulama başlattığınızda (tarayıcı veya metin düzenleyici gibi), işletim sistemi bir işlem oluşturur .
Python'da Multithreading nedir?
Python programlamasında çoklu okuma, bir süreçteki birden fazla iş parçacığının veri alanını ana iş parçacığı ile paylaştığı, iş parçacıkları içinde bilgi paylaşımını ve iletişimi kolay ve verimli hale getiren iyi bilinen bir tekniktir. İplikler işlemlerden daha hafiftir. İşlem kaynaklarını paylaşırken çoklu iş parçacıkları ayrı ayrı yürütülebilir. Çoklu okumanın amacı, aynı anda birden fazla görevi ve işlev hücresini çalıştırmaktır.
Çoklu İşlem nedir?
Çoklu işlem, birden çok ilgisiz işlemi aynı anda çalıştırmanıza olanak tanır. Bu süreçler, kaynaklarını paylaşmaz ve IPC aracılığıyla iletişim kurmaz.
Python Multithreading vs Multiprocessing
İşlemleri ve iş parçacıklarını anlamak için şu senaryoyu göz önünde bulundurun: Bilgisayarınızdaki bir .exe dosyası bir programdır. Açtığınızda, işletim sistemi onu belleğe yükler ve CPU onu çalıştırır. Şu anda çalışan programın vakasına işlem adı verilir.
Her sürecin 2 temel bileşeni olacaktır:
- Kod
- Veri
Artık bir işlem, iş parçacığı adı verilen bir veya daha fazla alt parça içerebilir . Bu , işletim sistemi mimarisine bağlıdır. Bir iş parçacığını, işlemin işletim sistemi tarafından ayrı ayrı yürütülebilecek bir bölümü olarak düşünebilirsiniz.
Başka bir deyişle, işletim sistemi tarafından bağımsız olarak çalıştırılabilen bir talimat akışıdır. Tek bir süreç içindeki iş parçacıkları, bu sürecin verilerini paylaşır ve paralelliği kolaylaştırmak için birlikte çalışmak üzere tasarlanmıştır.
Bu eğitimde öğreneceksiniz,
- Konu nedir?
- Süreç nedir?
- Multithreading nedir?
- Çoklu İşlem nedir?
- Python Multithreading vs Multiprocessing
- Neden Multithreading kullanılıyor?
- Python MultiThreading
- Diş ve Diş Açma modülleri
- Konu Modülü
- Diş Açma Modülü
- Kilitlenmeler ve Yarış koşulları
- Konuları senkronize etme
- GIL nedir?
- GIL'e neden ihtiyaç duyuldu?
Neden Multithreading kullanılıyor?
Çoklu okuma, bir uygulamayı birden çok alt göreve bölmenize ve bu görevleri aynı anda çalıştırmanıza olanak tanır. Çoklu iş parçacığını doğru kullanırsanız, uygulama hızınız, performansınız ve işlemenin tümü iyileştirilebilir.
Python MultiThreading
Python, hem çoklu işlem hem de çoklu okuma için yapıları destekler. Bu eğitimde, öncelikle çok iş parçacıklı uygulamaları python ile uygulamaya odaklanacaksınız . Python'da konuları işlemek için kullanılabilecek iki ana modül vardır:
- İplik modülü ve
- threading modülü
Bununla birlikte, python'da, global yorumlayıcı kilidi (GIL) adı verilen bir şey de vardır. Çok fazla performans kazanımına izin vermez ve hatta bazı çok iş parçacıklı uygulamaların performansını düşürebilir . Bu eğitimin ilerleyen bölümlerinde bununla ilgili her şeyi öğreneceksiniz.
Diş ve Diş Açma modülleri
Bu eğitimde öğreneceğiniz iki modül, diş modülü ve diş açma modülüdür .
Ancak, iş parçacığı modülü uzun süredir kullanımdan kaldırılmıştır. Python 3 ile başlayarak, eski olarak belirlendi ve yalnızca geriye dönük uyumluluk için __thread olarak erişilebilir .
Dağıtmayı düşündüğünüz uygulamalar için daha yüksek seviye diş açma modülünü kullanmalısınız. İş parçacığı modülü burada yalnızca eğitim amaçlı olarak ele alınmıştır.
Konu Modülü
Bu modülü kullanarak yeni bir iş parçacığı oluşturmak için sözdizimi aşağıdaki gibidir:
thread.start_new_thread(function_name, arguments)
Pekala, şimdi kodlamaya başlamak için temel teoriyi ele aldınız. Öyleyse, IDLE'nizi veya bir not defterinizi açın ve aşağıdakileri yazın:
import timeimport _threaddef thread_test(name, wait):i = 0while i <= 3:time.sleep(wait)print("Running %s\n" %name)i = i + 1print("%s has finished execution" %name)if __name__ == "__main__":_thread.start_new_thread(thread_test, ("First Thread", 1))_thread.start_new_thread(thread_test, ("Second Thread", 2))_thread.start_new_thread(thread_test, ("Third Thread", 3))
Dosyayı kaydedin ve programı çalıştırmak için F5'e basın. Her şey doğru yapılmışsa, görmeniz gereken çıktı budur:
Yarış koşulları ve bunları nasıl ele alacağınız hakkında ilerideki bölümlerde daha fazla bilgi edineceksiniz.
KOD AÇIKLAMASI
- Bu ifadeler, Python iş parçacıklarının çalıştırılması ve geciktirilmesi için kullanılan zaman ve iş parçacığı modülünü içe aktarır.
- Burada, start_new_thread metodu ile çağrılacak olan thread_test adlı bir fonksiyon tanımladınız . İşlev, dört yineleme için bir while döngüsü çalıştırır ve onu çağıran iş parçacığının adını yazdırır. Yineleme tamamlandığında, iş parçacığının yürütmeyi bitirdiğini belirten bir mesaj yazdırır.
- Bu, programınızın ana bölümüdür. Burada, basitçe start_new_thread yöntemini evre_test işlevi argüman olarak çağırırsınız .
Bu, argüman olarak ilettiğiniz fonksiyon için yeni bir iş parçacığı yaratacak ve onu çalıştırmaya başlayacaktır. Bunu (thread _ test) bir thread olarak çalıştırmak istediğiniz herhangi bir başka fonksiyonla değiştirebileceğinizi unutmayın.
Diş Açma Modülü
Bu modül, python'da iş parçacığının üst düzey uygulamasıdır ve çok iş parçacıklı uygulamaları yönetmek için fiili standarttır. İplik modülüne göre çok çeşitli özellikler sağlar.
Bu modülde tanımlanan bazı yararlı işlevlerin listesi aşağıdadır:
Fonksiyon adı | Açıklama |
activeCount () | Hala canlı olan Thread nesnelerinin sayısını verir |
currentThread () | Thread sınıfının geçerli nesnesini döndürür. |
numaralandır () | Tüm aktif Thread nesnelerini listeler. |
isDaemon () | İş parçacığı bir arka plan programı ise true döner. |
yaşıyor() | İş parçacığı hala yaşıyorsa doğru döndürür. |
İş Parçacığı Sınıfı yöntemleri | |
Başlat() | Bir iş parçacığının aktivitesini başlatır. Her iş parçacığı için yalnızca bir kez çağrılmalıdır, çünkü birden çok kez çağrılırsa bir çalışma zamanı hatası verir. |
koşmak() | Bu yöntem, bir iş parçacığının aktivitesini belirtir ve Thread sınıfını genişleten bir sınıf tarafından geçersiz kılınabilir. |
katılmak() | Join () yönteminin çağrıldığı iş parçacığı sonlandırılana kadar diğer kodun yürütülmesini engeller. |
Backstory: İş Parçacığı Sınıfı
İş parçacığı modülünü kullanarak çok iş parçacıklı programları kodlamaya başlamadan önce, Thread sınıfını anlamak çok önemlidir. Thread sınıfı, şablonu ve bir iş parçacığının python'daki işlemlerini tanımlayan birincil sınıftır.
Çok iş parçacıklı bir python uygulaması oluşturmanın en yaygın yolu, Thread sınıfını genişleten ve run () yöntemini geçersiz kılan bir sınıf bildirmektir.
Özet olarak Thread sınıfı, ayrı bir kontrol iş parçacığında çalışan bir kod sırasını belirtir .
Bu nedenle, çok iş parçacıklı bir uygulama yazarken aşağıdakileri yapacaksınız:
- Thread sınıfını genişleten bir sınıf tanımlayın
- __İnit__ yapıcısını geçersiz kılın
- Run () yöntemini geçersiz kıl
Bir iş parçacığı nesnesi oluşturulduktan sonra, start () yöntemi bu etkinliğin yürütülmesine başlamak için kullanılabilir ve join () yöntemi, geçerli etkinlik bitene kadar diğer tüm kodları engellemek için kullanılabilir.
Şimdi, önceki örneğinizi uygulamak için iş parçacığı modülünü kullanmayı deneyelim. Yine, IDLE'nizi ateşleyin ve aşağıdakileri yazın:
import timeimport threadingclass threadtester (threading.Thread):def __init__(self, id, name, i):threading.Thread.__init__(self)self.id = idself.name = nameself.i = idef run(self):thread_test(self.name, self.i, 5)print ("%s has finished execution " %self.name)def thread_test(name, wait, i):while i:time.sleep(wait)print ("Running %s \n" %name)i = i - 1if __name__=="__main__":thread1 = threadtester(1, "First Thread", 1)thread2 = threadtester(2, "Second Thread", 2)thread3 = threadtester(3, "Third Thread", 3)thread1.start()thread2.start()thread3.start()thread1.join()thread2.join()thread3.join()
Yukarıdaki kodu çalıştırdığınızda çıktı bu olacaktır:
KOD AÇIKLAMASI
- Bu kısım, önceki örneğimiz ile aynıdır. Burada, Python iş parçacıklarının yürütülmesini ve gecikmelerini işlemek için kullanılan zaman ve iş parçacığı modülünü içe aktarırsınız.
- Bu bitte, threading modülünün Thread sınıfını miras alan veya genişleten threadtester adlı bir sınıf yaratıyorsunuz . Bu, python'da iş parçacığı oluşturmanın en yaygın yollarından biridir. Ancak, uygulamanızda yalnızca yapıcıyı ve run () yöntemini geçersiz kılmalısınız. Yukarıdaki kod örneğinde görebileceğiniz gibi, __init__ yöntemi (yapıcı) geçersiz kılındı.
Benzer şekilde, run () yöntemini de geçersiz kıldınız . Bir iş parçacığı içinde yürütmek istediğiniz kodu içerir. Bu örnekte, thread_test () işlevini çağırdınız.
- Bu değerini alır thread_test () yöntemidir i , bir argüman olarak, her adımda 1 ile bunu azaltır ı Her bir yinelemede 0 olana kadar kod geri kalanında ve döngüler, o anda yürütülmesi ipliğin adı basar ve bekleme saniyeleri boyunca uyur (bu da bir argüman olarak alınır).
- thread1 = threadtester (1, "İlk Konu", 1)
Burada, bir iş parçacığı oluşturuyoruz ve __init__ içinde tanımladığımız üç parametreyi geçiyoruz. İlk parametre iş parçacığının kimliğidir, ikinci parametre evrenin adıdır ve üçüncü parametre ise while döngüsünün kaç kez çalışması gerektiğini belirleyen sayaçtır.
- thread2.start ()
Başlangıç yöntemi, bir iş parçacığının yürütülmesini başlatmak için kullanılır. Dahili olarak start () işlevi, sınıfınızın run () yöntemini çağırır.
- thread3.join ()
Join () yöntemi, diğer kodun yürütülmesini engeller ve çağrıldığı iş parçacığı bitene kadar bekler.
Zaten bildiğiniz gibi, aynı süreçte olan iş parçacıkları o işlemin belleğine ve verilerine erişebilir. Sonuç olarak, birden fazla iş parçacığı aynı anda verileri değiştirmeye veya erişmeye çalışırsa, hatalar ortaya çıkabilir.
Bir sonraki bölümde, iş parçacıkları mevcut erişim işlemlerini kontrol etmeden verilere ve kritik bölüme eriştiğinde ortaya çıkabilecek farklı karmaşıklık türlerini göreceksiniz.
Kilitlenmeler ve Yarış koşulları
Kilitlenmeleri ve yarış koşullarını öğrenmeden önce, eşzamanlı programlamayla ilgili birkaç temel tanımı anlamak faydalı olacaktır:
- Kritik Bölüm
Paylaşılan değişkenlere erişen veya bunları değiştiren ve atomik bir işlem olarak gerçekleştirilmesi gereken bir kod parçasıdır.
- Bağlam anahtarı
Bir CPU'nun bir görevden diğerine geçmeden önce bir iş parçacığının durumunu saklamak için izlediği süreçtir, böylece daha sonra aynı noktadan devam edilebilir.
Kilitlenmeler
Kilitlenmeler, geliştiricilerin python'da eşzamanlı / çok iş parçacıklı uygulamalar yazarken karşılaştıkları en korkulan sorundur. Çıkmazları anlamanın en iyi yolu, Yemek Filozofları Problemi olarak bilinen klasik bilgisayar bilimi örnek problemini kullanmaktır .
Yemek filozofları için sorun ifadesi şu şekildedir:
Beş filozof, şemada gösterildiği gibi beş tabak spagetti (bir tür makarna) ve beş çatal ile yuvarlak bir masaya oturuyor.
Herhangi bir zamanda, bir filozof ya yemek yiyor ya da düşünüyor olmalıdır.
Dahası, bir filozof spagetti yemeden önce yanındaki iki çatalı (yani sol ve sağ çatalları) almalıdır. Kilitlenme sorunu, beş filozofun hepsi aynı anda doğru çatallarını aldığında ortaya çıkar.
Filozofların her birinin bir çatalı olduğu için, hepsi diğerlerinin çatallarını indirmesini bekleyeceklerdir. Sonuç olarak hiçbiri spagetti yiyemeyecek.
Benzer şekilde, eşzamanlı bir sistemde, farklı iş parçacıkları veya süreçler (filozoflar) aynı anda paylaşılan sistem kaynaklarını (çatallar) almaya çalıştığında bir kilitlenme meydana gelir. Sonuç olarak, işlemlerin hiçbiri, başka bir işlem tarafından tutulan başka bir kaynağı bekledikleri için yürütme şansı bulamaz.
Yarış koşulları
Yarış koşulu, bir sistem aynı anda iki veya daha fazla işlemi gerçekleştirdiğinde ortaya çıkan istenmeyen bir program durumudur. Örneğin, şu basit for döngüsünü düşünün:
i=0; # a global variablefor x in range(100):print(i)i+=1;
Oluşturmak ise n bir kerede bu kodu çalıştırmak parçacığı sayısı, program yürütme tamamlandığında (parçacığı tarafından paylaşılan) i değerini belirleyemez. Bunun nedeni, gerçek bir çok iş parçacıklı ortamda, evrelerin üst üste gelebilmesidir ve bir evre tarafından alınan ve değiştirilen i'nin değeri, başka bir evre ona eriştiğinde bunlar arasında değişebilir.
Bunlar, çok iş parçacıklı veya dağıtılmış bir python uygulamasında ortaya çıkabilecek iki ana sorun sınıfıdır. Bir sonraki bölümde, konuları senkronize ederek bu sorunu nasıl aşacağınızı öğreneceksiniz.
Konuları senkronize etme
Yarış koşulları, kilitlenmeler ve diğer iş parçacığı tabanlı sorunların üstesinden gelmek için, iş parçacığı modülü Kilit nesnesini sağlar. Buradaki fikir, bir iş parçacığı belirli bir kaynağa erişmek istediğinde, o kaynak için bir kilit edinmesidir. Bir iş parçacığı belirli bir kaynağı kilitlediğinde, kilit serbest kalana kadar başka hiçbir iş parçacığı ona erişemez. Sonuç olarak, kaynakta yapılan değişiklikler atomik olacak ve yarış koşulları önlenecek.
Kilit, __thread modülü tarafından uygulanan düşük seviyeli bir ilkel senkronizasyondur . Herhangi bir zamanda bir kilit 2 durumdan birinde olabilir: kilitli veya kilidi açık. İki yöntemi destekler:
- elde etmek()
Kilit durumunun kilidi açıldığında, acquire () yönteminin çağrılması, durumu kilitli olarak değiştirecek ve geri dönecektir. Bununla birlikte, durum kilitliyse, release () yöntemi başka bir iş parçacığı tarafından çağrılana kadar acquire () çağrısı engellenir.
- serbest bırakmak()
Release () yöntemi, durumu kilidi açık olarak ayarlamak, yani bir kilidi serbest bırakmak için kullanılır. Kilidi alan değil, herhangi bir iş parçacığı tarafından çağrılabilir.
İşte uygulamalarınızda kilit kullanımına bir örnek. IDLE'nizi çalıştırın ve aşağıdakileri yazın:
import threadinglock = threading.Lock()def first_function():for i in range(5):lock.acquire()print ('lock acquired')print ('Executing the first funcion')lock.release()def second_function():for i in range(5):lock.acquire()print ('lock acquired')print ('Executing the second funcion')lock.release()if __name__=="__main__":thread_one = threading.Thread(target=first_function)thread_two = threading.Thread(target=second_function)thread_one.start()thread_two.start()thread_one.join()thread_two.join()
Şimdi F5'e basın. Bunun gibi bir çıktı görmelisiniz:
KOD AÇIKLAMASI
- Burada, threading.Lock () fabrika işlevini çağırarak basitçe yeni bir kilit oluşturuyorsunuz . Dahili olarak Lock (), platform tarafından sağlanan en etkili somut Kilit sınıfının bir örneğini döndürür.
- İlk ifadede, acquire () yöntemini çağırarak kilidi elde edersiniz. Kilit verildiğinde, konsola "edinilmiş kilit" yazdırırsınız . İş parçacığının çalışmasını istediğiniz tüm kodun yürütülmesi bittiğinde, release () yöntemini çağırarak kilidi serbest bırakırsınız.
Teori iyi, ama kilidin gerçekten çalıştığını nasıl anlarsınız? Çıktıya bakarsanız, yazdırma ifadelerinin her birinin bir seferde tam olarak bir satır yazdırdığını göreceksiniz. Daha önceki bir örnekte, birden çok iş parçacığının print () yöntemine aynı anda erişmesi nedeniyle gelişigüzel çıktıların yazdırıldığını hatırlayın. Burada, yazdırma işlevi yalnızca kilit elde edildikten sonra çağrılır. Böylece, çıktılar birer birer ve satır satır görüntülenir.
Kilitlerin dışında python, aşağıda listelendiği gibi iş parçacığı senkronizasyonunu işlemek için başka mekanizmaları da destekler:
- RLocks
- Semaforlar
- Koşullar
- Olaylar ve
- Engeller
Global Tercüman Kilidi (ve bununla nasıl başa çıkılacağı)
Python'un GIL'inin ayrıntılarına girmeden önce, gelecek bölümü anlamada faydalı olacak birkaç terim tanımlayalım:
- CPU'ya bağlı kod: Bu, doğrudan CPU tarafından yürütülecek herhangi bir kod parçasını ifade eder.
- G / Ç bağlantılı kod: bu, işletim sistemi aracılığıyla dosya sistemine erişen herhangi bir kod olabilir.
- CPython: Python'un referans uygulamasıdır ve C ve Python (programlama dili) ile yazılmış yorumlayıcı olarak tanımlanabilir.
Python'da GIL nedir?
Python'daki Global Yorumlayıcı Kilidi (GIL) , süreçlerle uğraşırken kullanılan bir işlem kilidi veya bir mutekstir. Bir iş parçacığının aynı anda belirli bir kaynağa erişebilmesini sağlar ve aynı zamanda nesnelerin ve bayt kodlarının aynı anda kullanılmasını engeller. Bu, performans artışında tek iş parçacıklı programlara fayda sağlar. Python'da GIL çok basit ve uygulanması kolaydır.
Belirli bir zamanda yalnızca bir iş parçacığının belirli bir kaynağa erişimi olduğundan emin olmak için bir kilit kullanılabilir.
Python'un özelliklerinden biri, her yorumlayıcı işleminde küresel bir kilit kullanmasıdır; bu, her işlemin python yorumlayıcısının kendisini bir kaynak olarak ele aldığı anlamına gelir.
Örneğin, hem CPU hem de 'G / Ç' işlemlerini gerçekleştirmek için iki iş parçacığı kullanan bir python programı yazdığınızı varsayalım. Bu programı çalıştırdığınızda, şu olur:
- Python yorumlayıcısı yeni bir süreç oluşturur ve iş parçacıkları oluşturur
- Thread-1 çalışmaya başladığında, önce GIL'i alacak ve kilitleyecektir.
- Eğer evre-2 şimdi çalıştırmak isterse, başka bir işlemci serbest olsa bile GIL'in serbest bırakılmasını beklemek zorunda kalacaktır.
- Şimdi, thread-1'in bir I / O işlemini beklediğini varsayalım. Bu zamanda, GIL'i serbest bırakacak ve thread-2 onu alacak.
- G / Ç işlemlerini tamamladıktan sonra, evre-1 şimdi çalıştırmak isterse, GIL'in evre-2 tarafından serbest bırakılmasını beklemek zorunda kalacaktır.
Bu nedenle, yorumlayıcıya herhangi bir zamanda yalnızca bir iş parçacığı erişebilir, bu da belirli bir zamanda python kodunu yürüten yalnızca bir iş parçacığı olacağı anlamına gelir.
Bu, tek çekirdekli bir işlemcide uygundur, çünkü iş parçacıkları işlemek için zaman dilimlemeyi kullanır (bu öğreticinin ilk bölümüne bakın). Bununla birlikte, çok çekirdekli işlemciler söz konusu olduğunda, birden çok iş parçacığı üzerinde çalışan CPU'ya bağlı bir işlev, aynı anda tüm mevcut çekirdekleri kullanmayacağı için programın verimliliği üzerinde önemli bir etkiye sahip olacaktır.
GIL'e neden ihtiyaç duyuldu?
CPython çöp toplayıcı, referans sayma olarak bilinen verimli bir bellek yönetimi tekniğini kullanır. İşleyiş şekli şöyledir: Python'daki her nesnenin, yeni bir değişken adına atandığında veya bir kaba eklendiğinde (tuple, liste vb.) Artırılan bir referans sayısı vardır. Benzer şekilde, referans kapsam dışına çıktığında veya del ifadesi çağrıldığında referans sayısı azaltılır. Bir nesnenin referans sayısı 0'a ulaştığında, çöp toplanır ve ayrılan bellek serbest bırakılır.
Ancak sorun, referans sayma değişkeninin diğer herhangi bir küresel değişken gibi yarış koşullarına yatkın olmasıdır. Bu sorunu çözmek için python geliştiricileri, global yorumlayıcı kilidini kullanmaya karar verdi. Diğer seçenek, her bir nesneye kilitlenmelerle sonuçlanacak ve acquire () ve release () çağrılarından kaynaklanan ek yükün artmasına neden olacak bir kilit eklemekti.
Bu nedenle, GIL, yoğun CPU bağlantılı işlemler çalıştıran çok iş parçacıklı python programları için önemli bir kısıtlamadır (bunları etkin bir şekilde tek iş parçacıklı hale getirir). Uygulamanızda birden çok CPU çekirdeğinden yararlanmak istiyorsanız, bunun yerine çoklu işlem modülünü kullanın.
Özet
- Python, çoklu okuma için 2 modülü destekler:
- __thread modülü: Diş açma için düşük seviyeli bir uygulama sağlar ve artık kullanılmamaktadır.
- threading module : Çoklu iş parçacığı için üst düzey bir uygulama sağlar ve mevcut standarttır.
- Diş çekme modülünü kullanarak bir diş oluşturmak için aşağıdakileri yapmanız gerekir:
- Thread sınıfını genişleten bir sınıf oluşturun .
- Yapıcısını geçersiz kılın (__init__).
- Run () yöntemini geçersiz kılın .
- Bu sınıfın bir nesnesini oluşturun.
- Start () yöntemi çağrılarak bir iş parçacığı yürütülebilir .
- Birleştirme () yöntemi, bu iplik (birleştirme çağrıldığı bir) yürütme bitene kadar diğer konuları engellemek için kullanılabilir.
- Birden fazla iş parçacığı paylaşılan bir kaynağa aynı anda eriştiğinde veya değiştirdiğinde bir yarış durumu oluşur.
- Konuları senkronize ederek önlenebilir.
- Python, iş parçacıklarını senkronize etmenin 6 yolunu destekler:
- Kilitler
- RLocks
- Semaforlar
- Koşullar
- Olaylar ve
- Engeller
- Kilitler, yalnızca kilidi almış belirli bir dişlinin kritik bölüme girmesine izin verir.
- Bir Kilidin 2 ana yöntemi vardır:
- acquire () : Kilit durumunu kilitli olarak ayarlar . Kilitli bir nesne çağrılırsa, kaynak serbest kalana kadar bloke eder.
- release () : Kilit durumunu kilidi açık olarak ayarlar ve geri döner. Kilitli olmayan bir nesnede çağrılırsa, yanlış döndürür.
- Global yorumlayıcı kilidi, bir seferde yalnızca 1 CPython yorumlayıcı sürecinin yürütülebileceği bir mekanizmadır.
- CPythons'ın çöp toplayıcısının referans sayma işlevini kolaylaştırmak için kullanıldı.
- Yoğun CPU bağlantılı işlemlere sahip Python uygulamaları yapmak için çoklu işlem modülünü kullanmalısınız.