Introduction of sync.Cond
sync.Cond
is a locking process that is used with certain conditions. sync.Cond
in the Golang synchronization package implements conditional variables that can be used in scenarios where multiple readers
are waiting for concurrent resources. Cond pooling point: multiple goroutines waiting, 1 goroutine notification event occurs. Each Cond is associated with a Lock
**(sync.Mutex or sync.RWMutex) that should be added when modifying the condition or calling the wait()
method, to protect the condition.
Why should we use sync.Cond
?
This condition is suitable for instructing the program that runs in the goroutine to execute it one by one. If you want to do it one by one then the signal()
method is executed to activate only one goroutine. Meanwhile, if you want to activate and execute the program using all goroutines then you can use the broadcast()
method.
Method Usage
NewCond()
is used to create a condition in a variableBroadcast()
is used to notify all goroutines so that they don’t have to wait anymoreSignal()
is used to notify a goroutine so that it does not have to wait anymore
Implementation and sample of sync.Cond
Look at the program that has been created below.
var locker = &sync.Mutex{}
var cond = sync.NewCond(locker)
var group = &sync.WaitGroup{}
func WaitCondition(value int) {
cond.L.Lock()
fmt.Println("waiting", value)
cond.Wait()
fmt.Println("Done", value)
cond.L.Unlock()
group.Done()
}
The function we have created is a condition to output the input of waitCondition
where we can print the value
sent to the function. Next we create the first one using the signal
method. The following main
function below is how to execute this sync.Cond
condition.
func main() {
for i := 0; i < 10; i++ {
group.Add(1)
go WaitCondition(i)
}
go func() {
for i := 0; i < 10; i++ {
time.Sleep(1 * time.Second)
cond.Signal()
}
}()
group.Wait()
}
If we run this program, the running goroutines are about 10, but they are still waiting for the condition that signal
. After we call cond.Signal()
on the next * goroutine*, the input sent will be printed gradually with a 1 second pause because we set sleep
. The results will not be sequential because the execution will run simultaneously using the active * goroutine*.
waiting 0
waiting 5
waiting 1
waiting 2
waiting 3
waiting 4
waiting 7
waiting 6
waiting 8
waiting 9
Done 0
Done 5
Done 1
Done 2
Done 3
Done 4
Done 7
Done 6
Done 8
Done 9
Then, what if we want to activate all the goroutines at the same time so that there is no need for a 1 second pause? Then if we want that, we need to change the original call cond.Signal()
to cond.Broadcast()
. That method will send a signal that all goroutines can be active simultaneously. Here is the command to run all the goroutines below.
func main() {
for i := 0; i < 10; i++ {
group.Add(1)
go WaitCondition(i)
}
go func() {
for i := 0; i < 10; i++ {
time.Sleep(1 * time.Second)
cond.Broadcast()
}
}()
group.Wait()
}
Conclusion
sync.Cond
is an asynchronize operation that we can use for some conditions where for example we want to execute large data with some conditions so that the * goroutine* that runs is selected not all of them run because we wait for the signal
which goroutine runs the command first. We can use various implementations to make the process of using goroutines more effective.