package main
import (
"fmt"
"runtime"
"sync"
"time"
)
var waitgroup = sync.WaitGroup{} // Better to use this way rather putting sleep to get all the Go routine executed
// This will not impact the performance due to static time sleep.
//var mutex = sync.RWMutex // This is the way to introduce Synchronization & Locking, & you will see its syntax more like we //have in Java7+ versions
func main() {
fmt.Println("Threads available : ", runtime.GOMAXPROCS(0)) // It returns the logical CPUs available or the previous settings //done to set the number CPUs to use
// & that number of CPU threads it can use. Here it also sets the number of CPUs to use, so if you give value < 1 then it will //not change the settings
// To get the optimal processing, set this number equal to number of core processors available for CPU intensive work else //you can give value bit greater than number
// of available logical processors. But don't give too high value as it cause more overhead for the scheduler to manage the //threads.
start := time.Now().Nanosecond()
var name string = "Nitin"
waitgroup.Add(3) // Here telling that we need to wait for 3 routines to compelete, just try reducing this number & check the //result
// if you give more number than the number of routines started, then you will get the error as this group will not get those many //Done() calls.
go prints(name)
// time.Sleep(20 * time.Microsecond)
go func() { // It being closure so it will be having access to variables of its enclosing function
// when this function is executed then current variable value will be used & it is not guaranteed when it will
// be executed. Here reference to 'name' variable which may cause issue
fmt.Println(name + " Agrawal")
time.Sleep(10 * time.Microsecond) // if you dont put sleep here then you will see race condition, to check this use -race in //execution command.
waitgroup.Done() // Every routine needs to declare when it is done, it is liek we have in Java for CountdownLatch & //CyclicBarrier
}()
// time.Sleep(1 * time.Microsecond) // this little wait here will give the chance to above routine to execute & below new value //will not be reflected.
go func(name string) { // Here name variable is Pass by Value, so it gets the value of the variable before it is changed in next //line.
fmt.Println(name + " Agrawal..Not changed")
time.Sleep(1 * time.Microsecond)
waitgroup.Done() // Every routine needs to declare when it is done, it is liek we have in Java for CountdownLatch & //CyclicBarrier
}(name)
name = "Changed"
waitgroup.Wait()
// time.Sleep(2 * time.Microsecond) // if you remove this then current main function will end before above go routine executes, //as above go routine
// is still within the scope of main lifetime.
end := time.Now().Nanosecond()
fmt.Println("Time taken : ", (end - start))
}
func prints(name string) {
fmt.Println(name)
time.Sleep(10 * time.Microsecond)
fmt.Println("After Wait....")
waitgroup.Done() // Every routine needs to declare when it is done, it is liek we have in Java for CountdownLatch & //CyclicBarrier
}
import (
"fmt"
"runtime"
"sync"
"time"
)
var waitgroup = sync.WaitGroup{} // Better to use this way rather putting sleep to get all the Go routine executed
// This will not impact the performance due to static time sleep.
//var mutex = sync.RWMutex // This is the way to introduce Synchronization & Locking, & you will see its syntax more like we //have in Java7+ versions
func main() {
fmt.Println("Threads available : ", runtime.GOMAXPROCS(0)) // It returns the logical CPUs available or the previous settings //done to set the number CPUs to use
// & that number of CPU threads it can use. Here it also sets the number of CPUs to use, so if you give value < 1 then it will //not change the settings
// To get the optimal processing, set this number equal to number of core processors available for CPU intensive work else //you can give value bit greater than number
// of available logical processors. But don't give too high value as it cause more overhead for the scheduler to manage the //threads.
start := time.Now().Nanosecond()
var name string = "Nitin"
waitgroup.Add(3) // Here telling that we need to wait for 3 routines to compelete, just try reducing this number & check the //result
// if you give more number than the number of routines started, then you will get the error as this group will not get those many //Done() calls.
go prints(name)
// time.Sleep(20 * time.Microsecond)
go func() { // It being closure so it will be having access to variables of its enclosing function
// when this function is executed then current variable value will be used & it is not guaranteed when it will
// be executed. Here reference to 'name' variable which may cause issue
fmt.Println(name + " Agrawal")
time.Sleep(10 * time.Microsecond) // if you dont put sleep here then you will see race condition, to check this use -race in //execution command.
waitgroup.Done() // Every routine needs to declare when it is done, it is liek we have in Java for CountdownLatch & //CyclicBarrier
}()
// time.Sleep(1 * time.Microsecond) // this little wait here will give the chance to above routine to execute & below new value //will not be reflected.
go func(name string) { // Here name variable is Pass by Value, so it gets the value of the variable before it is changed in next //line.
fmt.Println(name + " Agrawal..Not changed")
time.Sleep(1 * time.Microsecond)
waitgroup.Done() // Every routine needs to declare when it is done, it is liek we have in Java for CountdownLatch & //CyclicBarrier
}(name)
name = "Changed"
waitgroup.Wait()
// time.Sleep(2 * time.Microsecond) // if you remove this then current main function will end before above go routine executes, //as above go routine
// is still within the scope of main lifetime.
end := time.Now().Nanosecond()
fmt.Println("Time taken : ", (end - start))
}
func prints(name string) {
fmt.Println(name)
time.Sleep(10 * time.Microsecond)
fmt.Println("After Wait....")
waitgroup.Done() // Every routine needs to declare when it is done, it is liek we have in Java for CountdownLatch & //CyclicBarrier
}
package main
import (
"fmt"
"sync"
)
var wg = sync.WaitGroup{}
// Check select statement used in channels for graceful shutdown of channel apart from using defer func() to close the channels
func main() {
ch := make(chan int, 10)
wg.Add(2)
go func(ch <-chan int) { // This way we are making sure that this function will only receive the data from channel
for i := range ch { // This way you will iterate through the channel & it will fetch one data only unlike it fetches 2 items
// from Array, first is index & second is data at that index
fmt.Println(i)
}
for { // This is another way to iterate through the channel & this way you can get the information about when the channel is closed
// like shown below
if i, ok := <-ch; ok {
fmt.Println(i)
} else {
fmt.Println("Channel is closed...")
break
}
}
wg.Done()
}(ch)
go func(ch chan<- int) { // This way we are making sure that this function will only send the data to channel
for i := 0; i < 10; i++ {
ch <- i
}
close(ch) // If you don't use this statement to close the channel then you will get deadlock
// due to receiver loop at line#15 above, as it doesn't know when to stop as channel will be
// open & the range will continue to expect data from channel.
// Note : Close the channel only when you are done with pushing items to channel
wg.Done()
}(ch)
wg.Wait()
}
import (
"fmt"
"sync"
)
var wg = sync.WaitGroup{}
// Check select statement used in channels for graceful shutdown of channel apart from using defer func() to close the channels
func main() {
ch := make(chan int, 10)
wg.Add(2)
go func(ch <-chan int) { // This way we are making sure that this function will only receive the data from channel
for i := range ch { // This way you will iterate through the channel & it will fetch one data only unlike it fetches 2 items
// from Array, first is index & second is data at that index
fmt.Println(i)
}
for { // This is another way to iterate through the channel & this way you can get the information about when the channel is closed
// like shown below
if i, ok := <-ch; ok {
fmt.Println(i)
} else {
fmt.Println("Channel is closed...")
break
}
}
wg.Done()
}(ch)
go func(ch chan<- int) { // This way we are making sure that this function will only send the data to channel
for i := 0; i < 10; i++ {
ch <- i
}
close(ch) // If you don't use this statement to close the channel then you will get deadlock
// due to receiver loop at line#15 above, as it doesn't know when to stop as channel will be
// open & the range will continue to expect data from channel.
// Note : Close the channel only when you are done with pushing items to channel
wg.Done()
}(ch)
wg.Wait()
}