Geonode logo
Geonode Team

Geonode Team

Güncellenme: 7 Ekim 2026

Yayınlanma: 2 Eylül 2026

Eşzamanlılık ve Paralellik: Aralarındaki Fark Nedir?

Eşzamanlılık, aynı anda birçok şeyle ilgilenmekle ilgilidir. Paralellik ise aynı anda birçok şeyi yapmakla ilgilidir. Bu, ders kitaplarındaki standart tanımdır ve tek başına hiçbir şeyi açıklamaz. Bu ayrım, pratik bir soru sorduğunuz anda anlam kazanır: Neden iş parçacığı eklemek bir programı hızlandırırken, diğerini yavaşlatır? Bu makale, Python, Go ve Node dillerinin birbirinden nasıl farklı olduğunu ve iş yükünüzün aslında hangisine ihtiyaç duyduğunu nasıl anlayacağınızı ayrıntılı olarak açıklayarak bu soruya yanıt veriyor.

Bunu kimin ve neden yazdığına dair biraz arka plan bilgisi. Biz Geonode olarak proxy satışı yapıyoruz; bu da bizi bu konuyla sürekli iç içe getiriyor — web veri kazıma, tipik bir I/O sınırlı iş yüküdür ve “veri kazıyıcım yavaş” ifadesi, bize en sık yöneltilen sorunlardan biridir. O halde teoriye geçmeden önce dürüstçe şunu söyleyelim: Eğer kazıyıcınız her seferinde tek bir sayfa aldığı için yavaşsa, proxy satın almak onu hızlandırmayacaktır. Eşzamanlılık, kodunuzun bir özelliğidir. Yüz proxy uç noktası ve sıralı bir döngü, size yüz boşta duran uç noktası olan sıralı bir kazıyıcı verir. Önce eşzamanlılık sorununu çözün. Proxy'ler farklı bir sorunu çözer — eşzamanlılık çalıştıktan sonra, hedef sunucu aniden saniyede elli istek gönderen adrese hız sınırlaması uygulamaya başladığında karşılaştığınız sorunu. Her iki sorun da gerçektir. Ancak bunlar aynı sorun değildir ve aynı çözümü gerektirmez.

Bunu söyledikten sonra, aradaki farka gelelim.

Tek Cümlede Fark

Rob Pike’ın bu konuyla ilgili konuşmasında kullandığı ifade hâlâ en net olanıdır ve Go blogu bunu doğrudan şöyle belirtir:

Eşzamanlılık, “bağımsız olarak çalışan süreçlerin birleşimidir.”

Paralellik ise "(muhtemelen birbiriyle ilişkili) hesaplamaların eşzamanlı olarak yürütülmesidir."

Bunları iki kez okuyun, çünkü aradaki fark vurgunun nereye yapıldığıyla ilgilidir. Eşzamanlılık yapı ile ilgilidir — bir problemi bağımsız olarak ilerleyebilecek parçalara nasıl ayırdığınızla ilgilidir. Paralellik ise yürütme ile ilgilidir — bu parçalardan kaç tanesinin fiziksel olarak aynı anda çalıştığı.

İnsanların gözden kaçırdığı sonuç şudur: eşzamanlılık sizin yazdığınız bir şeydir, paralellik ise makinenin yaptığı bir şeydir. Hiçbir şeyin eşzamanlı olmadığı tek bir çekirdekte eşzamanlı bir program yazıp çalıştırabilirsiniz; bu program yine de eşzamanlı olacaktır. Bağımsız görevleri tanımlamışsınızdır; çalışma zamanı bunları birbirine karıştırır. Ve sekiz çekirdekte çalıştırılan eşzamanlı bir program, çalışma zamanı ve iş yükü izin verirse paralel hale gelebilir.

Bu asimetri, bu iki kelimenin birbirinin yerine kullanılamamasının nedenidir. Eşzamanlılık, paralelliği garanti etmeden paralelliği mümkün kılar. Eşzamanlı yapı olmadan paralellik ise hiç mümkün değildir.

Karışıklık Neden Devam Ediyor?

Üç neden var ve bunları sıralamak yardımcı olur.

Gözlemlenebilir davranış genellikle aynıdır. Tek bir çekirdekte çalışan bir eşzamanlı program ile dört çekirdekte çalışan bir paralel program, her ikisi de “birden fazla şeyin aynı anda gerçekleştiği” izlenimini verir. Dışarıdan bakıldığında, hangisiyle karşı karşıya olduğunuzu ayırt edemezsiniz. Bunu, çekirdek sayısını artırdığınızda ve hiçbir iyileşme görmediğinizde anlarsınız.

Her dilin terminolojisi tutarsızdır. Python’un threading modülü size eşzamanlılık sağlar, ancak tarihsel olarak paralellik sağlamaz. Python’un multiprocessing modülü ise her ikisini de sağlar. JavaScript’in async/await modülleri, kendi kodunuz için eşzamanlılık sağlar, ancak asla paralellik sağlamaz. Go’nun goroutine’leri ise GOMAXPROCS adresinde belirtildiği gibi eşzamanlılık ve paralellik sağlar. Belgelerde geçen aynı kelimeler, farklı ekosistemlerde farklı anlamlara gelir.

Çoğu zaman bunu önemsemenize gerek yoktur, ta ki birdenbire önemsemeniz gerekene kadar. I/O sınırlı bir iş yükü için bu ayrım neredeyse teorik bir konudur — eşzamanlılık tek başına size tüm avantajı sağlar. CPU'ya bağlı bir iş yükü için ise durum tamamen farklıdır, çünkü eşzamanlılık tek başına size hiçbir şey kazandırmaz. Sorun şu ki, insanlar I/O'ya bağlı sorunlarında işe yarayan kalıbı öğrenip bunu CPU'ya bağlı bir soruna uyguluyorlar.

Her Dilin Bunu Gerçekte Nasıl Yaptığı

Çalışma zamanıEşzamanlılık mekanizmasıKodunuz için gerçek paralellikNerede aksaklık yaşanır
Python (varsayılan derleme)threading, asyncioYalnızca multiprocessing aracılığıylaGIL, bayt kodu yürütmesini sıralı hale getirir
Python (serbest iş parçacıklı derleme)threading, asyncioEvet, iş parçacıkları paralel çalışırTek iş parçacıklı ek yük, ekosistem olgunluğu
Gogoroutinler + kanallarEvet, GOMAXPROCS'e kadarPaylaşılan durumun yine de senkronizasyona ihtiyacı var
Node.jsolay döngüsü, async/awaitYalnızca worker_threads veya alt işlemler aracılığıylaTek bir CPU'ya bağlı geri çağırma her şeyi engeller
Java / C#iş parçacıkları, iş parçacığı havuzlarıEvetPaylaşılan değiştirilebilir durumun karmaşıklığı
Rustasync + iş parçacıklarıEvetDerleyici, öncelikle doğru yazmanızı sağlar

Node.js, paralellik olmadan eşzamanlılığın en net örneğidir. Resmi belgeler bunu kesin bir şekilde ifade eder: olay döngüsü, "varsayılan olarak tek bir JavaScript iş parçacığı kullanılmasına rağmen, mümkün olduğunda işlemleri sistem çekirdeğine aktararak Node.js'nin engellemesiz G/Ç işlemleri gerçekleştirmesine olanak tanır." Çekirdek çok iş parçacıklıdır; JavaScript'iniz ise değildir. Döngü altı aşamadan geçer — zamanlayıcılar, bekleyen geri çağırmalar, boşta/hazırlık, yoklama, kontrol, geri çağırmaları kapatma — ve bir işlem bittiğinde, "çekirdek bunu Node.js'ye bildirir, böylece uygun geri çağırma yoklama kuyruğuna eklenerek sonunda yürütülür."

Bunun pratikteki sonucu doğrudan ortaya çıkar. Node’da on bin eşzamanlı HTTP isteği önemsiz bir sayıdır, çünkü bekleme işlemi çekirdekte gerçekleşir. İki saniye süren tek bir CPU’ya bağlı işlev, tüm süreci dondurur; çünkü onu çalıştıracak tek bir iş parçacığı vardır ve hiçbir şey onun önceliğini alamaz.

Go ise tam tersi bir yaklaşım benimser: goroutine’leri binlerce oluşturmak yeterince ucuzdur ve zamanlayıcı bunları işletim sistemi iş parçacıkları arasındGOMAXPROCS’e kadar dağıtır; bu değer varsayılan olarak kullanılabilir çekirdek sayısına eşittir. Dolayısıyla Go, aynı yapıdan hem eşzamanlılık hem de paralellik sağlar. Pike’ın bu konuyu ele almasının nedeni budur — bu ayrım, her ikisini de sunan ve dolayısıyla bunların birbiriyle karıştırılabileceği bir dilde en büyük öneme sahiptir.

Karar Verici Soru: İş Yükünüz I/O Sınırlı mı, Yoksa CPU Sınırlı mı?

Yukarıda anlatılan her şey, iş yükünüzle ilgili tek bir soruya indirgenebilir ve bu konuda varsayımda bulunmak yerine ölçüm yapmanızda fayda vardır.

I/O sınırlı olması, programınızın zamanının çoğunu bekleyerek geçirdiği anlamına gelir: bir ağ yanıtı, bir disk okuma işlemi veya bir veritabanı sorgusu için. Bekleme süresince CPU atıl durumdadır. Eşzamanlılık doğru ve yeterli cevaptır, çünkü eşzamanlılık, mevcut bekleme hâlâ devam ederken bir sonraki beklemeyi başlatmanıza olanak tanır. Paralellik ise esasen hiçbir şey katmaz — ağı bekleyen sekiz çekirdek, ağı bekleyen tek bir çekirdekten daha hızlı değildir.

CPU sınırlı olması, programınızın zamanının çoğunu hesaplama işlemleriyle geçirdiği anlamına gelir: ayrıştırma, sıkıştırma, karma oluşturma, dönüştürme. CPU doymuş durumdadır. Eşzamanlılık tek başına hiçbir şeyi değiştirmez — bir çekirdekte iki hesaplamayı birbirine karıştırarak yürütmek, bunları sırayla çalıştırmakla aynı toplam süreyi alır, buna ek olarak geçiş yükü de eklenir. Yalnızca paralellik yardımcı olur ve bu da fiziksel çekirdek sayısıyla sınırlıdır.

Hangisiyle karşı karşıya olduğunuzu öğrenmek için, tahminde bulunmak yerine ölçüm yapın. Linux'ttime'i çalıştırdığınızda hemen cevabı alırsınız: gerçek geçen süreyi, kullanıcı artı sistem CPU süresiyle karşılaştırın. Gerçek süre, CPU süresinden çok daha fazlaysa, bekliyorsunuz demektir — I/O sınırlısınız. Eğer süreler birbirine yakınsa, hesaplama yapıyorsunuz demektir — CPU sınırlısınız.

Web kazıma, her ikisini de sırayla içerdiği için yararlı bir örnektir. Sayfaları getirmek büyük ölçüde I/O sınırlıdır; ardından HTML'yi ayrıştırmak ise CPU sınırlıdır. Doğru mimari, sayfa alma işlemi için eşzamanlılığı ve ayrıştırma işlemi için paralelliği kullanır; yaygın bir hata ise her iki aşamaya da tek bir stratejiyi uygulamaktır. Tek iş parçacıklı bir ayrıştırıcıya 200 eşzamanlı sayfa alma işlemi yapan bir kazıyıcı, hızlı bir kazıyıcı değildir — arkasında bir kuyruk biriken hızlı bir sayfa alıcıdır.

Python'un GIL'i ve Serbest İş Parçacıklığının Getirdiği Değişiklikler

Python, durumunun gerçekten değişmiş olması ve bu konuda okuyacağınız bilgilerin çoğunun artık geçerliliğini yitirmiş olması nedeniyle ayrı bir bölüme layık.

Geçmişte: CPython'un Global Interpreter Lock'u (GIL), bir seferde yalnızca bir iş parçacığının Python bayt kodunu yürütmesine izin veriyordu. Bu nedenle iş parçacıkları eşzamanlılık sağlıyordu ancak paralellik sağlamıyordu. GIL, I/O işlemleri sırasında serbest bırakıldığından iş parçacıklı I/O sorunsuz çalışıyordu; ancak CPU'ya bağlı iş parçacıkları çalışmıyordu ve bunun için geçici çözüm olarak multiprocessing kullanılıyordu.

Neler değişti: 3.13 sürümünden itibaren CPython, GIL'in devre dışı bırakıldığı isteğe bağlı bir derleme sunmaktadır. Serbest iş parçacığı belgeleri bunu açıkça açıklamaktadır — "Serbest iş parçacıklı yürütme, mevcut CPU çekirdeklerinde iş parçacıklarını paralel olarak çalıştırarak mevcut işlem gücünün tam olarak kullanılmasını sağlar."

16 Haziran 2025 tarihinde Yönlendirme Konseyi tarafından "Final" statüsüyle kabul edilen PEP 779, serbest iş parçacığı özelliğini deneysel aşamadan resmi olarak desteklenen aşamaya geçirmek için kriterleri belirlemiş ve bu aşama için Python 3.14 sürümünü hedeflemiştir.

Bunu kullanmaya başlamadan önce dikkate almanız gereken dört pratik nokta:

Bu, varsayılan derleme değildir. Bunu kasıtlı olarak edinmeniz veya derlemeniz gerekir — kaynak koddan derlemek için --disable-gil yapılandırma seçeneğini kullanmanız gerekir. Hangi sürümü çalıştırdığınızı python -VV komutuyla kontrol edin; bu komut "free-threading build" ifadesini gösterir, ya da sys._is_gil_enabled() komutunu kullanın; GIL kapalıyken bu komut False değerini döndürür.

Tek iş parçacıklı kodlar yavaşlar. Belgelerde, pyperformance test paketinde "ortalama ek yükün macOS aarch64'te yaklaşık %1'den x86-64 Linux sistemlerinde %8'e kadar değiştiği" belirtilmektedir. PEP 779'da, Yönlendirme Konseyi'nin serbest iş parçacıklı Python'un "yaklaşık %10-15 daha yavaş olmasını" beklediği ve %15'in II. aşama için kesin hedef olduğu belirtilir; ayrıca bellek kullanımındaki %20'lik geometrik ortalama artış, "verimli ve güvenli serbest iş parçacıklılığın bedeli" olarak kabul edilir. Programınız tek iş parçacıklıysa, bu derleme doğrudan bir gerilemedir.

GIL’i çalışma zamanında geri getirebilirsiniz. Serbest iş parçacıklı derlemeler, PYTHON_GIL ortam değişkeni veya -X gil seçeneği aracılığıyla GIL etkinleştirilmiş olarak çalışmayı destekler — bu, bir bağımlılık düzgün çalışmadığında kullanışlıdır.

Bağımlılıklarınız sınırlayıcı faktördür. C uzantıları, serbest iş parçacığı desteğini bildirecek şekilde derlenmelidir. Ekosistem önemli ölçüde değişmiştir, ancak "benim makinemde saf Python ile çalışıyor" demek, "bilimsel yığınım çalışıyor" demekle aynı şey değildir.

Veri kazıma ve API çalışmalarında baskın olan I/O sınırlı durumlarda, bunların hiçbiri kararınızı değiştirmez: asyncio veya standart derlemedeki bir iş parçacığı havuzu, eşzamanlılığın sunabileceği her şeyi zaten size sağlar. Serbest iş parçacığı, veri alma aşaması değil, ayrıştırma aşaması darboğazınız olduğunda önemlidir.

Uygulamalı Örnek: 10.000 URL’nin Alınması

Somut rakamlar bu farkı açıkça ortaya koyar. Dört çekirdekli bir makinede her isteğin 200 ms sürdüğünü ve her yanıtın ayrıştırılmasının CPU’da 50 ms sürdüğünü varsayalım.

Sıralı. 10.000 × 250 ms = 2.500 saniye, yani yaklaşık 42 dakika. CPU, bu sürenin %80'inde boşta kalır.

Eşzamanlı alma, sıralı ayrıştırma. 100 eşzamanlı istekle, alma süresi gerçek zamanla yaklaşık 20 saniyeye düşer. Ayrıştırma süresi değişmez: 10.000 × 50 ms = 500 saniye. Toplamda yaklaşık 520 saniye, yani yaklaşık 9 dakika. 4,8 katlık bir iyileşme — ve zamanın nereye gittiğine dikkat edin. Veri alma, orijinal çalışma süresinin %80'ini oluştururken, şimdi yenisinin %4'ünü oluşturuyor. Değiştirmediğiniz ayrıştırma işlemi ise artık toplam sürenin %96'sını oluşturuyor.

Eşzamanlı veri alma, dört çekirdekte paralel ayrıştırma. Ayrıştırma süresi yaklaşık 125 saniyeye düşer. Toplamda yaklaşık 145 saniye, yani yaklaşık 2,5 dakika. Sıralı işleme göre 17 katlık bir iyileşme.

Bu rakamlardan üç ders çıkarılabilir.

Birincisi, en büyük kazanç, eşzamanlılık ile I/O sorununu gidermekten geliyor ve bu neredeyse hiçbir maliyeti yok — ekstra çekirdek yok, paylaşılan durum sorunları yok, sadece farklı bir döngü var.

İkincisi, baskın darboğazı giderdiğinizde, bir sonraki darboğaz hemen öne çıkıyor. Bu, Amdahl yasasının en pratik halidir: Çalışma süresinin %20'sini oluşturan bir aşamayı ne kadar mükemmel bir şekilde ortadan kaldırırsanız kaldırın, hızınızı %25'ten fazla artıramazsınız. Her zaman optimize etmeden önce ölçüm yapın ve sonrasında tekrar ölçüm yapın, çünkü sonuç değişir.

Üçüncüsü — ve burada ticari çıkarlarımız devreye giriyor, bu yüzden bunu uygun şekilde değerlendirin — tek seferde bir istekten yüz istek yapmaya geçtiğiniz anda, fark edilir hale gelirsiniz. Bir ana bilgisayara saniyede 500 istek gönderen tek bir adres, hız sınırlamasına tabi tutulur, ardından engellenir. Bu bir eşzamanlılık sorunu değildir ve ne kadar asyncio kullanırsanız kullanın bu sorunu çözemezsiniz; bu bir dağıtım sorunudur ve proxy'lerin varlık nedeni budur. Ev tipi trafiğimiz 0,79 $/GB'den, veri merkezi trafiğimiz ise 0,14 $/GB'den başlar; bu fiyatlar Eylül 2026'daki fiyatlandırma sayfamız üzerinden kontrol edilmiştir. Ancak sıraya dikkat edin: önce eşzamanlılık, ardından eşzamanlılık çözülemeyen bir sorun yarattığında proxy'ler. Bunun tersini yapmak, kullanma imkânınız olmayan bant genişliği için para ödemek anlamına gelir.

Eşzamanlılığın Artık Yarar Sağlamadığı Nokta

Eşzamanlılığı artırmak, önce azalan, ardından da negatif getirilerle sonuçlanır ve bu dönüm noktası çoğu kişinin beklediğinden daha erken gelir.

Bağlantı sınırları. İşletim sistemleri, açık dosya tanımlayıcılarına bir sınır getirir. Sunucular ise istemci başına eşzamanlı bağlantı sayısını sınırlar. Tek bir makineden gelen on bin eşzamanlı istek, CPU sınırına ulaşmadan çok önce bu sınırlardan birine ulaşır ve hata durumu genellikle net bir hata mesajı yerine kafa karıştırıcı bir hata olur.

Bellek. İşlemde olan her istek, tamponlar, ayrıştırılmış başlıklar ve bekleyen yanıt verilerini barındırır. Her biri 100 KB tutan on bin eşzamanlı istek, hiçbir şey yapmadan sadece bekleyen bir gigabayt bellek anlamına gelir.

Bağlam değiştirme ek yükü. İşletim sistemi iş parçacıkları bedava değildir — her biri bir yığın ve bir zamanlama maliyeti taşır. İşte tam da bu nedenle goroutinler ve coroutinler vardır: binlerce tane kullanmak makul olacak kadar ucuzdurlar; oysa binlerce işletim sistemi iş parçacığı kullanmak makul değildir.

Hedefin toleransı. Bağlantının diğer ucunun da kendi görüşleri vardır. Belirli bir oranın ötesinde, ek eşzamanlılık veri yerine 429 ve 503 hataları üretir ve daha fazlasını ekledikçe etkin veriminiz düşer. Bu, gerçek dünyada en sık karşılaşılan sınırdır ve en az ölçülen sınırdır; çünkü istekler hâlâ “çalışır” — sadece bir yeniden deneme döngüsünün özenle tekrarladığı hataları döndürürler.

Pratik yaklaşım pek de göz alıcı değildir: mütevazı bir eşzamanlılık sınırıyla başlayın, denenen istek sayısı yerine saniyede tamamlanan istek sayısını ölçün ve verim artmayı durdurana kadar bu sınırı artırın. Verim bir seviyeye ulaşacak, ardından düşecektir. Optimum nokta bu seviyededir ve genellikle sezgilerin öngördüğünden çok daha küçük bir sayıdır — çoğu zaman yüzler yerine onlarca.

İkisine de İhtiyacınız Olmadığında

Bunu belirtmekte fayda var, çünkü “eşzamanlı hale getir” artık bir refleks haline gelmiştir.

İş gerçekten küçükse. Her biri 200 ms süren yüz istek, sıralı olarak 20 saniye eder. Bu işlem her gece bir cron görevinde çalışıyorsa, 20 saniye sorun değildir; üstelik sabah saat 3’te hata verdiğinde eşzamanlı kodun hata ayıklaması daha zordur.

Sıralama, gereksinimin bir parçası olduğunda. Bazı iş akışları, öğeleri kesin bir sırayla işlemek zorundadır; aksi takdirde her adım bir önceki sonuca bağlı olur. Burada eşzamanlılık sadece yararsız olmakla kalmaz; yalnızca yük altında ortaya çıkan hataların kaynağıdır.

Darboğaz tamamen başka bir yerde olduğunda. Veritabanı yazma işlemleri kısıtlayıcı faktörse, 200 eşzamanlı okuyucu aynı kilidin önünde sadece daha uzun bir kuyruk oluşturur. Asıl darboğazı giderin. Seri bir kaynağın yukarısındaki eşzamanlılık, yavaş bir programı bellek sorunu olan yavaş bir programa dönüştürür.

Paylaşılan durum karmaşıksa. Paylaşılan, değiştirilebilir duruma dokunan eşzamanlı kod senkronizasyona ihtiyaç duyar ve bu konuda hata yapmak en kötü türden hatalara yol açar — aralıklı, yüke bağlı ve makinenizde tekrarlanamayan hatalar. Hız artışı 2 kat ise ve durum karmaşıksa, mantıkla değerlendirebileceğiniz sıralı kod genellikle daha iyi bir mühendislik kararıdır.

Ve bizim için önemli olan durum: Eğer önemsemeyen bir siteden günde birkaç yüz sayfa veri topluyorsanız, ne eşzamanlılığa ne de proxy’lere ihtiyacınız vardır. Nazik bir gecikmeyle bir döngü içinde tek bir requests çağrısı doğru cevaptır ve size ihtiyacınız olmayan bir plan satmaktansa bunu söylemeyi tercih ederiz.

İnsanlar Ayrıca Şunu Soruyor

Eşzamanlılık ile paralellik arasındaki en basit fark nedir?

Eşzamanlılık, aynı anda birçok şeyle ilgilenmektir — bu, programın yazılma şeklinin yapısal bir özelliğidir. Paralellik ise aynı anda birçok şeyi yapmaktır — bu, programın yürütülme şeklinin fiziksel bir özelliğidir. Eşzamanlılık, paralelliği mümkün kılar; ancak onu gerçekleştiremez.

Eşzamanlılık olmadan paralellik olabilir mi?

Burada tartışılan anlamda yararlı bir şekilde olmaz. Paralel yürütme, dağıtılabilecek bağımsız iş birimlerini gerektirir ve bu birimlerin tanımlanması eşzamanlılığın anlamıdır. SIMD gibi donanım düzeyinde paralellik bir istisnadır — programınızda herhangi bir eşzamanlı yapı olmaksızın, veriler üzerinde tek bir komut akışını paralel hale getirir.

Python GIL hâlâ var mı?

Evet, varsayılan derlemede. 3.13 sürümünden itibaren CPython, GIL’in devre dışı bırakıldığı isteğe bağlı bir serbest iş parçacıklı derleme de sunmaktadır ve PEP 779, bu derlemeyi 3.14 sürümünü hedefleyerek resmi olarak desteklenen statüye taşımıştır. Varsayılan derlemede GIL hâlâ mevcuttur; dolayısıyla, kasıtlı olarak serbest iş parçacıklı bir yorumlayıcı yüklemediğiniz sürece GIL mevcuttur.

Asenkron, çoklu iş parçacığı ile aynı şey midir?

Hayır. Asenkron eşzamanlılık, açık await noktalarında işbirliğine dayalı geçişe sahip tek bir iş parçacığı kullanır; bu nedenle kodunuzun bir seferde yalnızca bir parçası çalışır ve geçişler yalnızca yazdığınız yerlerde gerçekleşir. Çoklu iş parçacığı ise, herhangi bir yerde gerçekleşebilen öncelikli geçişe sahip birkaç işletim sistemi iş parçacığı kullanır. Asenkron işlemeyi anlamak daha kolaydır; iş parçacıkları, çalışma zamanı izin verdiği durumlarda gerçek paralellik sağlayabilir.

Kaç tane eşzamanlı istek göndermeliyim?

Düşündüğünüzden daha az. Yaklaşık 10 ile başlayın, saniye başına tamamlanan istek sayısını ölçün ve bu sayı artmayı durdurana kadar artırın. Üst sınır genellikle makinenizin kapasitesinden ziyade hedef sunucunun toleransına bağlıdır ve bu noktayı aştığınızda ekstra eşzamanlılık, verim yerine hatalara yol açar.

Eşzamanlılık kodumu hızlandırır mı?

Sadece bir şeyi bekliyorsanız. G/Ç sınırlı işlerde kazançlar büyüktür. Tek çekirdekteki CPU sınırlı işlerde ise, geçiş yükü nedeniyle eşzamanlılık işleri biraz yavaşlatır — paralelliğe ihtiyacınız vardır; bu da birden fazla çekirdek ve bunları kullanabilen bir çalışma zamanı ortamı anlamına gelir.

Çoklu işlem (multiprocessing) ile çoklu iş parçacığı (multithreading) arasındaki fark nedir?

İş parçacıkları (threads), tek bir işlem (process) içinde belleği paylaşır; bu da iletişimi ucuz, ancak paylaşılan durumu tehlikeli hale getirir. İşlemlerin ise ayrı bellekleri vardır; bu da onları güvenli kılar ancak iletişimi pahalı hale getirir. Varsayılan olarak derlenmiş Python’da, CPU’ya bağlı işler için gerçek paralelliği işlemler aracılığıyla elde edersiniz; iş parçacıkları ise I/O’ya bağlı işler için eşzamanlılık sağlar.

Eşzamanlı istekleri çalıştırmak için proxy’lere ihtiyacım var mı?

Doğası gereği hayır. Eşzamanlılık, sizi o kadar görünür hale getirirse ki hedef, geldiğiniz adresi hız sınırlamasına tabi tutar veya engellerse, proxy'lere ihtiyacınız olur. Cömert bir kota sunan bir API'ye veya tarama izniniz olan bir siteye karşı, eşzamanlılık tek başına yeterlidir. Adres başına sınırlama uygulayan bir siteye karşı ise dağıtım bir kısıtlama haline gelir — ve bu, kodunuzu düzeltmekten ayrı bir satın alma işlemidir.

Sonuç

Bu ayrımı akılda tutmak önemlidir; çünkü “bunu nasıl daha hızlı hale getirebilirim?” gibi belirsiz bir soruyu, test edilebilir bir cevabı olan somut bir soruya dönüştürür: Bekliyor muyum, yoksa hesaplama mı yapıyorum?

Eğer bekliyorsanız, eşzamanlılığa ihtiyacınız vardır ve bunu dilinizin sağladığı her türlü biçimde kullanmanız gerekir. Kazanç büyüktür, genellikle ekstra donanım maliyeti gerektirmez ve tüm yaygın çalışma zamanlarında mevcuttur. Hesaplama yapıyorsanız, eşzamanlılık tek başına size bir fayda sağlamaz ve gerçek paralelliğe ihtiyacınız vardır — işlemler, işçi iş parçacıkları, çekirdekler arası goroutinler veya Python durumunda, kendi artı ve eksilerini değerlendirmeniz gereken serbest iş parçacıklı bir yorumlayıcı.

Çoğu gerçek program, aşamalar halinde her ikisini de içerir ve sıralama, seçimden daha önemlidir. En belirgin darboğazı giderin, tekrar ölçüm yapın ve sonucun değişmiş olmasını bekleyin. %80 oranında ağa bağlı olan bir iş akışı, ağı düzelttiğiniz anda %96 oranında ayrıştırmaya bağlı hale gelir ve ikinci optimizasyon, ilkinden tamamen farklı bir çalışma gerektirir.