Çünkü Rekabet Zordur

Eşzamanlılık, bir programın "devam eden" birden fazla görevi yönetme yeteneğidir aynı zamanda - mutlaka paralel olması gerekmez. paralellik bu infaz birden fazla fiziksel çekirdekte eş zamanlı. İki kavram arasındaki karışıklık birçok sorunun kaynağıdır. hatalar ve kötü mimari kararlar.

2026'da her biri farklı ödünleşimlere sahip beş ana rekabet modeli var. Hayır mutlak "en iyi" model vardır: seçim iş yükünün türüne bağlıdır (G/Ç'ye bağlı vs.) CPU'ya bağlı), dil, ekosistem ve gecikme gereksinimleri.

Model 1: İşletim Sistemi Konuları (Java, C++)

En geleneksel model: her eşzamanlılık birimi bir iplik işletim sisteminin. Çekirdek planlamayı, bağlam anahtarlarını ve iletişimi yönetir muteks korumalı paylaşılan bellek aracılığıyla iş parçacıkları arasında.

// Java: thread tradizionale vs virtual thread (Java 21)
// Thread OS tradizionale — costoso: ~1MB stack, scheduling kernel
Thread platformThread = new Thread(() -> {
    processRequest(); // blocca il thread OS durante I/O
});
platformThread.start();

// Virtual Thread (Java 21, Project Loom) — leggero: ~2KB stack iniziale
Thread virtualThread = Thread.ofVirtual().start(() -> {
    processRequest(); // blocca solo il virtual thread, non il carrier
});

// Un milione di virtual thread sono praticabili
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    for (int i = 0; i < 1_000_000; i++) {
        executor.submit(() -> handleRequest());
    }
} // attende il completamento

Artıları: Basit zihinsel model, birden fazla çekirdeğin otomatik olarak kullanılması, olgun kütüphaneler

Aykırı: Pahalı işletim sistemi iş parçacıkları (1MB+ yığın, geçiş yükü), paylaşılan bellek yarışı koşulları, binlerce iş parçacığıyla sınırlı ölçeklendirme

Ne zaman: CPU'ya bağlı çalışma, iş parçacığı havuzuyla Java/C++, karışık yükler

Desen 2: Tek İş Parçacığı Olay Döngüsü (Node.js, JavaScript)

JavaScript tek iş parçacıklıdır: yalnızca bir yürütme iş parçacığı ve bunu gerçekleştiren bir olay döngüsü vardır. geri aramaları yönetir. Eşzamansız G/Ç (ağ, dosya sistemi) işletim sistemine devredilir aracılığıyla libuv ve tamamlanan işlemler geri arama kuyruğuna alınır.

// Node.js: event loop in azione
// Tutto esegue sullo stesso thread — nessun race condition!

const http = require('http');

http.createServer((req, res) => {
    // Questa callback non blocca il thread
    fetchUserData(req.userId)
        .then(user => {
            return fetchOrders(user.id); // altra I/O non bloccante
        })
        .then(orders => {
            res.json({ user, orders });
        })
        .catch(err => res.status(500).json({ error: err.message }));
}).listen(3000);

// Async/await (zucchero sintattico sopra Promise):
async function handleRequest(req, res) {
    const user = await fetchUserData(req.userId);   // non blocca il thread
    const orders = await fetchOrders(user.id);       // non blocca il thread
    res.json({ user, orders });
}

Artıları: Yarış koşulu yok (tek iş parçacığı), G/Ç bağlantılı için çok yüksek eşzamanlılık, devasa npm ekosistemi

Aykırı: CPU'ya bağlı her şeyi engeller, geri arama cehennemi (zaman uyumsuz/beklemeyle hafifletilir), gerçek paralellik için Worker Threads

Ne zaman: Birçok eşzamanlı G/Ç isteğine, gerçek zamanlı uygulamalara, BFF katmanına sahip API sunucusu

Model 3: Goroutin ve Kanal (Go)

Git uygular Sıralı Süreçlerin İletişimi (CSP): ultra hafif goroutinler (2KB başlangıç yığını, dinamik olarak büyür) yazılan kanallar aracılığıyla iletilir. Git mantrası: "Hafızayı paylaşarak iletişim kurmayın; hafızayı iletişim kurarak paylaşın."

// Go: goroutine e channel
package main

import (
    "fmt"
    "sync"
)

// Fan-out/Fan-in pattern con goroutine
func processItems(items []Item) []Result {
    results := make(chan Result, len(items))
    var wg sync.WaitGroup

    for _, item := range items {
        wg.Add(1)
        go func(i Item) {           // avvia goroutine — ~2KB stack
            defer wg.Done()
            result := processItem(i)  // eseguito concorrentemente
            results <- result
        }(item)
    }

    // Chiudi il channel quando tutte le goroutine completano
    go func() {
        wg.Wait()
        close(results)
    }()

    // Raccoglie i risultati
    var collected []Result
    for r := range results {
        collected = append(collected, r)
    }
    return collected
}

// Channel per comunicazione sicura tra goroutine
func producer(ch chan<- int) {
    for i := 0; i < 10; i++ {
        ch <- i    // invia sul channel (blocca se pieno)
    }
    close(ch)
}

func consumer(ch <-chan int) {
    for v := range ch {     // riceve finché il channel è aperto
        fmt.Println(v)
    }
}

Artıları: Ultra hafif goroutinler (milyonlarca geçerli), kanallar yarış koşullarını önler, çalışma zamanı planlamayı yönetir

Aykırı: CSP modeli öğrenme gerektirir, kanal kapatılmazsa goroutine sızıntısı, Go 1.18'den önce jenerik yok

Ne zaman: Yüksek G/Ç eş zamanlılığı, veri hatları ve CLI araçlarıyla arka uç hizmetleri

Desen 4: Eşzamansız/Bekleme (Python, Rust)

Eşzamansız/bekleme işbirlikçi rekabet: görevler açıkça vazgeçiyor G/Ç bekleme noktalarında kontrol (await). JavaScript olay döngüsünün aksine (yerleşik çalışma zamanı), Python ve Rust açık bir çalışma zamanı gerektirir (asyncio, Tokyo).

// Python: asyncio con TaskGroup (Python 3.11+)
import asyncio
import aiohttp

async def fetch_url(session: aiohttp.ClientSession, url: str) -> str:
    async with session.get(url) as response:
        return await response.text()

async def fetch_all_parallel(urls: list[str]) -> list[str]:
    async with aiohttp.ClientSession() as session:
        # TaskGroup garantisce che tutti i task completino o vengano cancellati
        async with asyncio.TaskGroup() as tg:
            tasks = [tg.create_task(fetch_url(session, url)) for url in urls]

    return [task.result() for task in tasks]

# Rust: Tokio async/await (zero-cost)
use tokio::time::{sleep, Duration};

async fn fetch_data(id: u64) -> String {
    sleep(Duration::from_millis(100)).await;  // simula I/O
    format!("data_{}", id)
}

#[tokio::main]
async fn main() {
    // Join concorrente senza allocazioni aggiuntive (zero-cost)
    let (r1, r2, r3) = tokio::join!(
        fetch_data(1),
        fetch_data(2),
        fetch_data(3),
    );
    println!("{}, {}, {}", r1, r2, r3);
}

Artıları: Bekleme noktaları üzerinde açık kontrol, paylaşılan yığında yarış koşulları yok, Rust'ta sıfır maliyet

Aykırı: "Async hastalığı" (eşzamansız çağrılırsa her işlev eşzamansız olmalıdır), daha karmaşık hata ayıklama

Ne zaman: G/Ç bağlantılı için Python (web kazıma, API çağrıları), yüksek performanslı sistemler için Rust

Model 5: Aktör Modeli (Erlang/Elixir, Akka)

Aktör modeli en izole olanıdır: her aktörün kendi özel durumu vardır ve iletişim kurar. sadece mesaj yoluyla. Paylaşılan bir hafıza yok, muteksler yok; her aktör bağımsız hafif bir süreç.

// Elixir: GenServer (actor model)
defmodule Counter do
  use GenServer

  # Interfaccia pubblica
  def start_link(initial \\ 0) do
    GenServer.start_link(__MODULE__, initial, name: __MODULE__)
  end

  def increment() do
    GenServer.call(__MODULE__, :increment)
  end

  def get_count() do
    GenServer.call(__MODULE__, :get)
  end

  # Implementazione (private)
  def init(initial), do: {:ok, initial}

  def handle_call(:increment, _from, count) do
    {:reply, count + 1, count + 1}   # reply, valore_risposta, nuovo_stato
  end

  def handle_call(:get, _from, count) do
    {:reply, count, count}
  end
end

# La BEAM VM può avere milioni di processi leggeri
# con supervisione automatica (OTP supervisor tree)

Artıları: Tam izolasyon (aktör çökmesi yayılmaz), tasarım gereği hata toleransı, yerel olarak dağıtılmış

Aykırı: Mesaj serileştirme yükü, birçok aktörün olduğu sistemlerde hata ayıklama karmaşıktır

Ne zaman: Hataya dayanıklı dağıtılmış sistemler, telekomünikasyon, gerçek zamanlı oyun, milyonlarca bağlantıyla IoT

Karşılaştırmalı Karşılaştırma

Yarışma: Model Seçimi Rehberi

  • Birçok G/Ç isteği (web API sunucusu): Goroutine veya Node.js olay döngüsüne gidin; her ikisi de on binlerce eşzamanlılığa ölçeklenir
  • CPU'ya bağlı (ML çıkarımı, kodlama): Çalışan havuzlarına sahip Java veya Go OS iş parçacıkları — tüm çekirdekleri kullanın
  • Ultra düşük gecikme süresi (ticaret, oyun): Rust Tokyo veya Go — çalışma zamanında sıfır ek yük
  • Dağıtılmış hata toleransı (telco, IoT): Elixir/Erlang Aktör modeli — yerel denetim ağacı
  • Veri bilimi, komut dosyası oluşturma: G/Ç için Python asyncio, CPU'ya bağlı çoklu işlem
  • Java kurumsal ekibi: Java 21 Virtual Threads — klasik iş parçacıklarıyla aynı zihinsel model, goroutine gibi ölçekler

Sonuçlar

Evrensel olarak üstün bir rekabet modeli yoktur. Doğru seçim şunlara bağlıdır: iş yükü (G/Ç vs CPU), ekip tarafından (beceriler ve tercihler), ekosistem tarafından (mevcut kitaplıklar) ve işlevsel olmayan gereksinimler (gecikme, verim, hata toleransı).

Serinin sonraki makaleleri her modeli ayrıntılı olarak ele alıyor: Şununla başlayalım: Node.js'nin en yanlış anlaşılan bileşeni olan JavaScript olay döngüsü.