လွယ်လွယ်ပြောရင် Thread ဆိုတာ Program တစ်ခုထဲမှာ တစ်ပြိုင်နက် အလုပ်လုပ်နေတဲ့ “အလုပ်သမား” တစ်ယောက်ချင်း ပါ။ Program တစ်ခုက အလုပ်သမား တစ်ယောက်တည်း ခန့်ထားရင် (single-thread) အလုပ်တစ်ခု ပြီးမှ နောက်တစ်ခုကို လုပ်နိုင်တယ်။ အလုပ်သမား လေးငါးယောက် ခန့်ထားရင် (multi-thread) အလုပ်တွေ တစ်ပြိုင်နက် လည်ပတ်နိုင်တယ်။

လက်ဖက်ရည်ဆိုင်နဲ့ ဥပမာပေးရအောင်။ ဆိုင်မှာ စားပွဲထိုး တစ်ယောက်တည်း ရှိတယ် ဆိုပါစို့။ ဧည့်သည် တစ်ယောက် လက်ဖက်ရည် မှာတယ် — စားပွဲထိုးက မီးဖိုချောင် သွားတယ်၊ လက်ဖက်ရည် ဖျော်တယ်၊ ပြန်လာတယ်၊ ချပေးတယ်။ ပြီးမှ နောက်ဧည့်သည်ဆီ သွားတယ်။ ဒါက single-thread။ ဧည့်သည် များလာရင် တန်းစီစောင့်ရတယ်၊ စိတ်ညစ်စရာ။

အခု စားပွဲထိုး ၄ ယောက် ထားကြည့်ပါ။ တစ်ယောက်က မှာတာ မှတ်တယ်၊ တစ်ယောက်က ဖျော်တယ်၊ တစ်ယောက်က ချပေးတယ်၊ တစ်ယောက်က ပိုက်ဆံ ကောက်တယ် — တစ်ပြိုင်နက် လည်ပတ်နေတယ်။ ဆိုင်တစ်ခုတည်း (Program တစ်ခု) ထဲမှာ အလုပ်သမား ၄ ယောက် (Thread ၄ ခု) အလုပ်လုပ်နေတာနဲ့ တူတယ်။ ဒါက multi-thread။

ဒီနေရာမှာ “Process” နဲ့ “Thread” ကို ခွဲထားဖို့ လိုတယ်။ Process ဆိုတာ ဆိုင်တစ်ခုလုံး — ကိုယ်ပိုင် မီးဖိုချောင်၊ ကိုယ်ပိုင် ငွေစာရင်း၊ ကိုယ်ပိုင် နေရာနဲ့ သီးသန့် လည်ပတ်နေတဲ့ အရာ။ ဥပမာ Chrome browser တစ်ခုလုံးက Process တစ်ခု။ Thread ဆိုတာ အဲဒီ ဆိုင်ထဲက စားပွဲထိုးတွေ — ဆိုင်ရဲ့ မီးဖိုချောင်၊ ငွေစာရင်း (memory) ကို အတူတူ သုံးကြတယ်။ Memory ကို အတူတူ သုံးတာက အားသာချက်လည်း ဖြစ်၊ ပြဿနာလည်း ဖြစ် — ဆက်ကြည့်ရအောင်။

နေ့တိုင်းသုံးနေတဲ့ နေရာတွေမှာ thread တွေ ဝှက်ထားတယ် —

Music player မှာ သီချင်းဖွင့်နေတဲ့ thread တစ်ခု၊ playlist download ဆွဲနေတဲ့ thread တစ်ခု၊ ခလုတ် နှိပ်တာ စောင့်နေတဲ့ thread တစ်ခု — သုံးခုလုံး တစ်ပြိုင်နက် လည်နေလို့ သီချင်း နားထောင်ရင်း download ဆွဲလို့ ရတာ
Web server တစ်ခုက လူ ၁၀၀၀ တစ်ပြိုင်နက် ဝင်လာရင် တောင်းဆိုမှုတစ်ခုချင်းစီကို thread တစ်ခုစီနဲ့ ကိုင်တယ်။ Thread တစ်ခု ရှိရင် လူ ၉၉၉ ယောက် စောင့်နေရမယ်
Game တစ်ခုမှာ ရုပ်ပုံ ဆွဲနေတဲ့ thread၊ အသံ ဖွင့်နေတဲ့ thread၊ ကစားသမား နှိပ်တာ ဖတ်နေတဲ့ thread

ဒါပေမယ့် thread တွေ memory အတူတူ သုံးတာက ပြဿနာ တစ်ခု ဖန်တီးတယ် — “race condition”။ လက်ဖက်ရည်ဆိုင်က မုန့်ဗူးကို ဥပမာယူကြည့်ပါ။ ဗူးထဲမှာ မုန့် တစ်ချပ်ပဲ ကျန်တယ်။ စားပွဲထိုး နှစ်ယောက်က တစ်ပြိုင်နက် လက်လှမ်းတယ် — နှစ်ယောက်လုံး “ဗူးထဲမှာ ရှိသေးတယ်” လို့ ထင်ပြီး ယူလိုက်ကြတယ်။ ရလဒ်? တစ်ချပ်တည်းကို နှစ်ယောက် ယူမိသလို ဖြစ်တယ်။ Program မှာလည်း အဲဒီလိုပဲ — thread နှစ်ခုက variable တစ်ခုတည်းကို တစ်ပြိုင်နက် ပြောင်းမိရင် data ပျက်တယ်။

ဒါကို ဖြေရှင်းတဲ့နည်းက “lock” (ဒါမှမဟုတ် mutex) — မုန့်ဗူးကို သော့ခတ်ထားသလိုပဲ။ သော့ ကိုင်ထားတဲ့ စားပွဲထိုးပဲ ဗူးကို ဖွင့်လို့ ရတယ်၊ ပြီးမှ သော့ ပြန်ပေး၊ နောက်တစ်ယောက် ယူ။ ရိုးရှင်းတယ်၊ ဒါပေမယ့် သော့ကို မေ့ပြီး ပြန်မပေးမိရင် (deadlock) ကျန်တဲ့ သူတွေ ထာဝရ စောင့်နေရတယ်။ Thread programming ရဲ့ ခက်ခဲတဲ့ အပိုင်းက ဒါပဲ။

Python သမားတွေ သိထားသင့်တဲ့ အချက်တစ်ခု ရှိတယ် — “GIL” (Global Interpreter Lock)။ CPython မှာ thread တွေ ဘယ်လောက်များများ၊ တကယ် တစ်ပြိုင်နက် run နေတာက thread တစ်ခု တည်း (CPU-bound အလုပ်တွေအတွက်)။ စားပွဲထိုး ၄ ယောက် ရှိပေမယ့် မီးဖိုချောင် တစ်ခန်းတည်း ရှိလို့ တစ်ယောက်ချင်းစီ ဝင်ချက်ရသလိုပေါ့။ ဒါကြောင့် Python မှာ CPU အလုပ်များတဲ့ အလုပ်တွေကို ပြိုင်လုပ်ချင်ရင် thread အစား multiprocessing (ဆိုင်ခွဲ ဖွင့်သလို Process ခွဲတာ) ကို သုံးကြတယ်။ I/O စောင့်ရတဲ့ အလုပ်တွေ (download ဆွဲတာ၊ file ဖတ်တာ) ကျတော့ thread က အဆင်ပြေတယ်။

နောက်တစ်ခါ program တစ်ခု “hang” နေတယ် ဆိုရင် တွေးကြည့်ပါ — စားပွဲထိုး တစ်ယောက်တည်း ရှိတဲ့ ဆိုင်မှာ သူ မီးဖိုချောင်ထဲ ပိတ်မိနေသလိုပဲ။ Thread များများ ရှိရင် တစ်ယောက် ပိတ်မိလည်း ကျန်တဲ့ သူတွေ ဆက်အလုပ်လုပ်နိုင်တယ်။ ဒါပါပဲ thread ရဲ့ အနှစ်ချုပ်။ 🙂