পাঠ ১৭.৬

Future, Task, এবং Thread

Putting It All Together: Futures, Tasks, and Threads

Chapter 16-এ thread, এই chapter-এ async — দু'টোই concurrency-এর model। কিন্তু কোনটা কখন ব্যবহার করব? দু'টো একসাথে use করা যায় কিনা? এই পাঠে আমরা এদের মধ্যে rough mental model তৈরি করব এবং দেখব কীভাবে combine করতে হয়।

তিনটা মডেল — granularity

  • Thread — OS managed, তুলনামূলক heavy (memory, context switch overhead)। Concurrency thread-এর মধ্যে। Fire-and-forget pattern।
  • Task — runtime managed, lightweight। Concurrency thread-এর মধ্যে এবং task-এর মধ্যেও (একটা task multiple future সামলাতে পারে)।
  • Future — Rust-এর সবচেয়ে granular concurrency unit; runtime executor task সামলায়, task future সামলায়।

কোনটা কখন

  • CPU-bound কাজ (heavy compute, parallelizable) → thread
  • I/O-bound কাজ (network, file, অনেক wait) → async
  • দু'টোই দরকার — thread + async একসাথে

আসলে অধিকাংশ production runtime (যেমন Tokio) multithreaded by defaultwork stealing করে: কোনো thread idle হয়ে গেলে অন্য thread-এর queue থেকে task নিয়ে আসে। ফলে throughput ভালো হয়।

Thread + async একসাথে

নিচের code-এ একটা thread blocking কাজ (i.e. compute-heavy বা legacy sync API) করছে; main task async-এ message receive করছে। দু'টোর মাঝে bridge হচ্ছে trpl::channel:

src/main.rsrust
use std::{thread, time::Duration};

fn main() {
    let (tx, mut rx) = trpl::channel();

    thread::spawn(move || {
        for i in 1..11 {
            tx.send(i).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    trpl::block_on(async {
        while let Some(message) = rx.recv().await {
            println!("{message}");
        }
    });
}

এই pattern বাস্তবে এমন জায়গায় কাজে লাগে — মনে করো একটা video encoding thread (CPU-heavy) আর একটা UI loop (event-driven, async)। Encoding thread chunk শেষ হলে channel-এ message পাঠায়, UI সেটা async-এ receive করে progress bar update করে।

পার্থক্য সংক্ষেপে

  • Thread thread::spawn দিয়ে — OS scheduler ঠিক করে কখন চলবে।
  • Task trpl::spawn_task দিয়ে — runtime scheduler নিয়ন্ত্রণ করে।
  • Thread blocking sync API-র সাথে স্বাভাবিক; async runtime-এ blocking call করলে runtime থমকে যাবে।
  • Async-এর benefit বেশি I/O-heavy বা অনেক simultaneous connection-এ (যেমন server)।

এই পাঠ থেকে যা শিখলে

  • Granularity — thread > task > future; runtime-ই task-কে thread-এ map করে।
  • CPU-bound → thread; I/O-bound → async; দু'টোই দরকার হলে combine।
  • Modern async runtime work stealing করে — multi-thread + async একসাথে।
  • Thread আর async-এর মাঝে trpl::channel দিয়ে communicate — একটা real-world pattern।
  • Async runtime-এ blocking call অপ্রত্যাশিতভাবে অন্য task-কে starve করতে পারে; দরকার হলে আলাদা thread-এ পাঠাও।