Skip to content

Instantly share code, notes, and snippets.

@mugli
Created May 20, 2021 08:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mugli/e2670015363eb7bca5ee4894f6c3242a to your computer and use it in GitHub Desktop.
Save mugli/e2670015363eb7bca5ee4894f6c3242a to your computer and use it in GitHub Desktop.
Concurrency in Go
/*
A data race happens when processes have to access the same variable concur
rently i.e. one process reads from a memory location while another simultaneously
writes to the exact same memory location.
*/
func main() {
number := 0;
go func(){
number++ //reading and modifying the value of 'number'
}()
fmt.Println(number) //reading the value of 'number'
}
// We can avoid data races by using channels or locks.
// They will allow us to synchronize memory access to all shared mutable data
// Fan-In: join data from multiple inputs into a single entity.
func fanIn(mychannel1, mychannel2 <-chan string) <-chan string {
outChannel := make(chan string)
var wg sync.WaitGroup
wg.Add(2)
go func() {
for s := range mychannel1 {
outChannel <- s
}
wg.Done()
}()
go func() {
for s := range mychannel2 {
outChannel <- s
}
wg.Done()
}()
go func() {
wg.Wait()
// Closing outChannel will help the consumer to range over it
close(outChannel)
}()
return outChannel
}
// Fan-Out: to divide the data from a single source into multiple smaller chunks.
func process(s string) {
// process
}
func main() {
v := []string{"a", "b", "c"}
for _, s := range v {
go process(s)
}
}
func foo() <-chan string {
mychannel := make(chan string)
go func() {
for i := 0; ; i++ {
mychannel <- fmt.Sprintf("%s %d", "Counter at : ", i)
}
close(mychannel)
}()
return mychannel // returns the channel as returning argument
}
func main() {
mychannel := foo() // foo() returns a channel.
for i := range mychannel {
fmt.Printf("%d\n", i)
}
fmt.Println("Done with Counter")
}
/*
The rules:
There are three rounds. Two partners.
In each round, both partners will have to process data.
A partner cannot move on to the next round until their partner is done with processing.
*/
type Data struct {
processorName string
waitForPartner chan bool
}
func process(processorName string) <-chan Data {
dataChannel := make(chan Data)
waitForPartner := make(chan bool)
go func() {
for i := 0; ; i++ {
dataChannel<- Data{ processorName, waitForPartner }
// Process takes random time
time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
<-waitForPartner
}
}()
return dataChannel
}
func fanIn(inChannel1, inChannel2 <-chan Data) <-chan Data {
outChannel := make(chan Data)
go func() {
for {
outChannel <- <-inChannel1
}
}()
go func() {
for {
outChannel <- <-inChannel2
}
}()
return outChannel
}
func main() {
processedChannel := fanIn(process("Processor 1"), process("Processor 2"))
for round := 0; round < 3; round++ {
data1 := <-processedChannel
fmt.Println(data1)
data2 := <-processedChannel
fmt.Println(data1)
data1.waitForPartner <- true
data2.waitForPartner <- true
fmt.Printf("Done with round %d\n", round+1)
}
fmt.Println("Done with the processing")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment