DEV Community

Pasindu Dewviman
Pasindu Dewviman

Posted on

Golang Concurrency සරලව - Buffered Channels

අද අපි බලමු වැදගත් කොටසක් වන Buffered Channels ගැන. මේකත් අපි අපේ සුපුරුදු "කුස්සියේ උදාහරණයෙන්" (Kitchen Analogy) තේරුම් ගනිමු.

සාමාන්‍ය Channel එකේ ගැටලුව (Unbuffered Channels)
අපි කලින් ඉගෙන ගත්ත සාමාන්‍ය Channel එකක් හරියට අතින් අතට බඩු මාරු කරනවා වගේ වැඩක්.

Chef (Sender): පීසා එකක් හැදුවොත්, වේටර් (Receiver) ඇවිත් ඒක අතට ගන්නකම් Chef ට ඒක අතේ තියාගෙන බලන් ඉන්න වෙනවා (Block වෙනවා).

වේටර් ආවේ නැත්නම්, Chef ට ඊළඟ පීසා එක හදන්න බැහැ. කුස්සිය හිරවෙනවා.

විසඳුම: Buffered Channels (බෆර්ඩ් චැනල්ස්) 📦
Buffered Channel එකක් කියන්නේ හරියට කුස්සියේ තියෙන කෑම මේසයක් වගේ. වේටර් එනකම් බලන් ඉන්නේ නැතුව, Chef ට පුළුවන් හදපු කෑම පිඟන් ටික මේසෙ උඩින් තියලා දිගටම උයන්න.

Go වලදී අපි මේකට "Buffer Capacity" (ධාරිතාව) කියලා කියනවා.

Code Example:

package main

import "fmt"

func main() {
    // අපි මේසයක් හදනවා පීසා 3ක් තියන්න පුළුවන් (Capacity = 3)
    // දැන් Chef ට වේටර් නැති වුනත් පීසා 3ක් මේකේ තියන්න පුළුවන්.
    kitchenTable := make(chan string, 3)

    // පීසා මේසෙට යවනවා (Send)
    kitchenTable <- "Pizza 1"
    kitchenTable <- "Pizza 2"
    kitchenTable <- "Pizza 3"

    fmt.Println("Chef: මම පීසා 3ම හැදුවා. වේටර් තාම නෑ, ඒත් මම හිරවෙලා නෑ!")

    // 4 වෙනි එකක් දාන්න ගියොත් විතරක් Chef හිරවෙනවා (මොකද මේසෙ ඉඩ ඉවරයි).
}
Enter fullscreen mode Exit fullscreen mode

මේ නිසා අපේ ප්‍රෝග්‍රෑම් එක වඩාත් කාර්යක්ෂම වෙනවා. මොකද යවන කෙනාට (Sender) ගන්න කෙනා (Receiver) එනකම් හැම වෙලාවෙම බලන් ඉන්න ඕනේ නැහැ.

Channel එක වසා දැමීම (Closing Channels) 🚪
කුස්සියේ වැඩ ඉවර වුනාම Chef අනිවාර්යයෙන්ම කියන්න ඕනේ "අදට වැඩ ඉවරයි, කුස්සිය වහනවා" කියලා. නැත්නම් වේටර්ලා (Receivers) රෑ එළි වෙනකම් හිස් කුස්සිය දිහා බලාගෙන ඉඳීවි (Deadlock).

Go වලදී අපි මේකට close() function එක පාවිච්චි කරනවා.

වැදගත්ම දේ: අපි Channel එකක් close කළාම, ගන්න කෙනාට (Receiver) දැනගන්න පුළුවන් "ආහ්! තව දත්ත එන්නේ නෑ" කියලා.

මේ සඳහා අපිට Range Loop එකක් පාවිච්චි කරන්න පුළුවන්.

Code Example:

package main

import "fmt"

func main() {
    orderQueue := make(chan string, 2)
    // Chef වෙනම වැඩ පටන් ගන්නවා (Goroutine)
    go func() {
        orderQueue <- "Burger"
        orderQueue <- "Fries"

        // වැඩ ඉවරයි! කුස්සිය වහනවා.
        close(orderQueue) 
        fmt.Println("Chef: කුස්සිය වැහුවා (Channel Closed)")
    }()

    // වේටර්: Channel එක close වෙනකම් එන හැම දේම ගන්නවා
    for order := range orderQueue {
        fmt.Println("Received:", order)
    }
    fmt.Println("Waiter: හරි, වැඩ ඉවරයි. මම ගෙදර යනවා.")
}
Enter fullscreen mode Exit fullscreen mode

Output:

Received: Burger
Received: Fries
Chef: කුස්සිය වැහුවා (Channel Closed)
Waiter: හරි, වැඩ ඉවරයි. මම ගෙදර යනවා.

වැදගත් කරුණු (Summary)

  • Buffered Channels (make(chan type, capacity)): දත්ත කිහිපයක් ගබඩා කර තැබිය හැකි Channels වේ. මෙය Sender සහ Receiver අතර තදබදය අඩු කරයි.
  • Closing Channels (close(ch)): දත්ත යවා අවසන් බව Receiver ට දැනුම් දීමට භාවිතා කරයි.
  • Range Loop (for msg := range ch): Channel එක close වන තුරු දිගටම දත්ත ලබා ගැනීමට මෙය භාවිතා කරයි.

Top comments (0)