Aplikasi toko online mengerjakan banyak pekerjaan yang sebagian besar waktunya dihabiskan untuk menunggu: memanggil API harga, membaca file laporan, atau menyimpan log ke disk. Pada model sinkron (synchronous), thread yang menjalankan pekerjaan tersebut berhenti menunggu sampai operasi selesai, dan thread itu tidak dapat dipakai untuk pekerjaan lain. Pada model asinkron (asynchronous), thread dibebaskan begitu operasi dimulai, lalu runtime memanggil kelanjutan kode ketika hasil sudah siap. Bab ini membandingkan kedua model melalui satu program yang sama.
Perbedaan Model Eksekusi #
| Aspek | Sinkron | Asinkron |
|---|---|---|
| Thread saat menunggu | Terikat sampai operasi selesai | Dibebaskan ke thread pool |
| Urutan eksekusi | Persis mengikuti urutan penulisan kode | Kelanjutan dijadwalkan setelah hasil siap |
| Skalabilitas I/O | Satu thread tersita untuk satu operasi aktif | Sedikit thread dapat melayani banyak operasi |
Thread pool adalah kumpulan thread yang disiapkan runtime untuk menjalankan pekerjaan latar. Pada aplikasi server, setiap permintaan yang menahan thread berarti satu kapasitas pelayanan ikut tertahan, sehingga jumlah permintaan yang dapat dilayani serentak menurun.
Contoh: Pekerjaan Sinkron dan Asinkron #
Program berikut menjalankan dua versi pekerjaan. Versi sinkron memakai loop komputasi, sedangkan versi asinkron memulai dua penundaan Task.Delay secara serentak:
static void KerjaSinkron(string nama)
{
Console.WriteLine($"{nama}: mulai");
double checksum = 0;
for (int i = 0; i < 10_000_000; i++)
{
checksum += Math.Sqrt(i);
}
Console.WriteLine($"{nama}: selesai");
}
static async Task MuatUnduhAsync(string nama)
{
Console.WriteLine($"Unduhan {nama}: dimulai");
await Task.Delay(150);
Console.WriteLine($"Unduhan {nama}: selesai");
}
static async Task ProsesLokalAsync()
{
Console.WriteLine("Proses lokal: dimulai");
await Task.Delay(50);
Console.WriteLine("Proses lokal: selesai");
}
// Pemanggil:
Console.WriteLine("--- Versi sinkron ---");
KerjaSinkron("A");
KerjaSinkron("B");
Console.WriteLine("--- Versi asinkron ---");
Task unduhan = MuatUnduhAsync("laporan-penjualan.csv");
Task proses = ProsesLokalAsync();
await unduhan;
await proses;Output yang Dihasilkan:
--- Versi sinkron ---
A: mulai
A: selesai
B: mulai
B: selesai
--- Versi asinkron ---
Unduhan laporan-penjualan.csv: dimulai
Proses lokal: dimulai
Proses lokal: selesai
Unduhan laporan-penjualan.csv: selesaiMari kita bedah bagian asinkronnya:
Task unduhan = MuatUnduhAsync(...): method asinkron berjalan sampaiawaitpertama, mencetak pesan “dimulai”, lalu kendali kembali ke pemanggil selagi penundaan 150 ms berjalan.Task proses = ProsesLokalAsync(): operasi kedua dimulai tanpa menunggu unduhan selesai; pesan “dimulai” tercetak sebelum kendali kembali lagi.await proses: pesan “Proses lokal: selesai” muncul lebih dulu karena penundaannya hanya 50 ms.await unduhan: pesan unduhan menyusul setelah 150 ms penuh terlampaui.
Bab berikutnya memperkenalkan tipe Task dan Task<T> sebagai wadah pekerjaan asinkron yang sedang kita tunggu.