[৪.৪] সিঙ্কগ্রুপ ( SyncGroup )
Go প্রোগ্রামিং এ Sync প্যাকেজ, প্রোগ্রামের ধারাবাহিকতা রক্ষায় সাহায্য করে। Mutex, WaitGroup, Pool, Once, Read এবং Write mutex এবং condition variable ইত্যাদির সাহায্যে প্রোগ্রামকে ধারাবাহিকভাবে চালানো হয়।
মিউটেক্স (Mutex)
Mutex হল মিউচুয়াল এক্সক্লুশনের সংক্ষিপ্তরুপ। Mutex একাধিক গোরুটিনকে একসাথে একটি শেয়ার্ড রিসোর্স অ্যাক্সেস করতে বাধা দেয়। একটি নির্দিষ্ট সময় শুধুমাত্র একটি গো-রুটিনকে শেয়ার করা ডেটাতে নিরাপদ অ্যাক্সেস প্রদান করার জন্য Mutex ব্যবহার করা হয়।
একটি Mutex এ দুটি অবস্থা থাকে – locked এবং unlocked । যখন একটি গো-রুটিনকে একটি মিউটেক্সে লক করা হয় তখন এটিকে আনলক না করা পর্যন্ত অন্য সব গো-রুটিন ব্লকে থাকে।
উদাহরণ –
package main
import (
"fmt"
"sync"
)
var counter int
var mutex sync.Mutex
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go increment(&wg)
}
wg.Wait()
fmt.Println("Counter:", counter)
}
func increment(wg *sync.WaitGroup) {
mutex.Lock()
defer mutex.Unlock()
defer wg.Done()
counter++
}
// Output :
// Counter: 10
এই উদাহরণে, আমরা শেয়ার্ড ভেরিয়েবল counter অ্যাক্সেস সিঙ্ক্রোনাইজ করতে একটি মিউটেক্স ব্যবহার করেছি। তারপর প্রতিটি গোরুটিন counter ভেরিয়েবল অ্যাক্সেস করার আগে মিউটেক্স লক করে দিয়েছি এবং এটি আপডেট করার পর আবার আনলক করে দিয়েছি। এতে করে এটি নিশ্চিত হয় যে শুধুমাত্র একটি গোরুটিন একবারে counter ভেরিয়েবল অ্যাক্সেস করতে পারে।
Read / Write মিউটেক্স
sync.RWMutex প্যাকেজ reader / writer mutex প্রোভাইড করে। এর কাজ মিউটেক্স মেথডের মতোই শুধু পার্থক্য এটি RLock এবং RUnlock এর সাহায্যে কনকারেন্টলি reads করতে পারে।
var i = 10
mutex := &sync.RWMutex{}
mutex.Lock()
// only one Goroutine can access this code at a time
i++
mutex.Unlock()
mutex.RLock()
i++ // concurrent reads
mutex.RUnlock()
sync.Map
sync.Map হল Go map এর কনকারেন্ট ভার্সন যার সাহায্যে আমরা নিচের কাজগুলো করতে পারি :
১। Store(interface{}, interface{}) এর সাহায্যে এলিমেন্ট Add করতে পারি।
২। Load(interface) interface{} এর সাহায্যে এলিমেন্ট Retrieve করতে পারি।
৩। Delete(interface{}) এর সাহায্যে এলিমেন্ট Remove করতে পারি।
৪। Range এর সাহায্যে এলিমেন্ট Iterate করতে পারি।
package main
import (
"fmt"
"sync"
"time"
)
var arrTest = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var minicache sync.Map
func towrite(text string) {
for _, v := range arrTest {
minicache.Store(v, text)
time.Sleep(10 * time.Millisecond)
}
}
func main() {
go towrite("test1")
go towrite("test2")
go func() {
time.Sleep(10 * time.Millisecond)
for _, v := range arrTest {
if val, ok := minicache.Load(v); ok {
fmt.Println(v, val)
} else {
fmt.Println(v, "not get")
}
time.Sleep(10 * time.Millisecond)
}
}()
time.Sleep(10 * time.Second)
}
Output :
1 test2
2 test1
3 test2
4 test1
5 test2
6 test1
7 test2
8 test1
9 test2
10 test2