Python, eş zamanlı görev yürütme yoluyla uygulama performansını artırmak için güçlü iş parçacığı yetenekleri sunar. Bununla birlikte, kontrolsüz iş parçacıkları kaynak rekabeti ve verimsizliğe yol açabilir. Bu makale, yaygın tuzaklardan kaçınmaya ve performansı en üst düzeye çıkarmaya odaklanarak, Python’da kuyruklar kullanarak etkili iş parçacığı tekniklerini ele almaktadır.
İçindekiler
- Python’da İş Parçacıkları
- Kuyruklarla İş Parçacıklarını Yönetme
- Doğru Yaklaşımı Seçme: İş Parçacıkları ve Çok İşlemli İşlem
Python’da İş Parçacıkları
Python iş parçacıkları, birden fazla fonksiyonun görünüşte eş zamanlı olarak yürütülmesini sağlar. Bu, bir iş parçacığının diğerlerini engellemeden harici kaynaklar için beklediği G/Ç bağlı işlemler (ağ istekleri, dosya işleme) için özellikle avantajlıdır. Bununla birlikte, CPython’daki Global Yorumlayıcı Kilidi (GIL), CPU bağlı görevler için gerçek paralelliği sınırlar; yalnızca bir iş parçacığı bir seferde Python yorumlayıcısının kontrolünü elinde tutabilir. Bu nedenle, iş parçacıklarının etkinliği öncelikle G/Ç bağlı işlemlerle gerçekleşir.
Kuyruksuz basit iş parçacığı örneğini ele alalım:
import threading
import time
def worker(name):
print(f"İş Parçacığı {name}: başlıyor")
time.sleep(2) # G/Ç bağlı işlemi simüle et
print(f"İş Parçacığı {name}: bitiyor")
threads = []
for i in range(5):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join()
print("Tüm iş parçacıkları bitti")
Bu, her biri worker
fonksiyonunu çalıştıran beş iş parçacığı oluşturur. İşlevsel olsa da, eş zamanlı iş parçacığı sayısı üzerinde kontrol eksikliği vardır ve sistemi çok sayıda görevle aşırı yükleyebilir.
Kuyruklarla İş Parçacıklarını Yönetme
Eş zamanlı iş parçacığı yürütmesini kontrol etmek ve kaynak tükenmesini önlemek için queue.Queue
kullanın. Kuyruk, iş parçacığı havuzu ve işleme arasında görevleri yöneten bir arabellek görevi görür. İş parçacıkları, kuyruk boşalana kadar sürekli olarak görevleri alır ve işler. Bu yaklaşım eşzamanlılığı düzenler ve kaynakları verimli bir şekilde yönetir.
İşte queue.Queue
kullanan geliştirilmiş bir örnek:
import threading
import time
import queue
def worker(q):
while True:
try:
item = q.get(True, 1) # 1 saniye boyunca engelle, boşsa istisna oluştur
print(f"İş Parçacığı {threading.current_thread().name}: {item} işleniyor")
time.sleep(2) # G/Ç bağlı işlemi simüle et
print(f"İş Parçacığı {threading.current_thread().name}: {item} bitti")
q.task_done()
except queue.Empty:
break
q = queue.Queue()
num_threads = 3 # Eş zamanlı iş parçacıklarını kontrol et
for i in range(10): # Görev sayısı
q.put(i)
threads = []
for i in range(num_threads):
t = threading.Thread(target=worker, args=(q,), daemon=True) # Ana iş parçacığı bittiğinde daemon iş parçacıkları sonlanır
threads.append(t)
t.start()
q.join() # Tüm kuyruk öğelerinin işlenmesini bekle
print("Tüm görevler bitti")
Bu örnek, görevleri (0-9) tutmak için queue.Queue
kullanır. Sadece üç iş parçacığı eş zamanlı olarak çalışır ve kuyruktan çeker. q.join()
, ana iş parçacığının görev tamamlanmasını beklemesini sağlar. daemon=True
, askıya alınmaları önlemek için ana iş parçacığı bittiğinde çalışan iş parçacıklarının sonlanmasını sağlar.
Doğru Yaklaşımı Seçme: İş Parçacıkları ve Çok İşlemli İşlem
Bu geliştirilmiş yaklaşım daha iyi kontrol, kaynak yönetimi ve ölçeklenebilirlik sunar. CPU bağlı görevler için, GIL sınırlaması nedeniyle CPython’da iş parçacıklarından çok işlemli işlem (multiprocessing
modülünü kullanarak) genellikle daha verimlidir. Görevlerinizin G/Ç bağlı mı yoksa CPU bağlı mı olduğuna bağlı olarak uygun yaklaşımı seçin.