Table of Contents
Mutex
package main
import (
"fmt"
"sync"
)
type Counter struct {
mu sync.Mutex
count int
}
func (c *Counter) IncrementCount() {
c.mu.Lock()
c.count++
fmt.Println(c.count)
c.mu.Unlock()
}
func (c *Counter) GetCount() int {
c.mu.Lock()
defer c.mu.Unlock()
return c.count
}
func main() {
wg := sync.WaitGroup{}
counter := &Counter{}
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
counter.IncrementCount()
}()
}
wg.Wait()
fmt.Printf("Final count = %d\n", counter.GetCount())
}
Output
1
2
3
4
5
6
7
8
9
10
Final count = 10
Program exited.
Channel Workers Processing Tasks (Incrementing Numbers)
package main
import (
"fmt"
"sync"
)
/*
type Counter struct {
mu sync.Mutex
count int
}
func (c *Counter) IncrementCount() {
c.mu.Lock()
c.count++
fmt.Println(c.count)
c.mu.Unlock()
}
func (c *Counter) GetCount() int {
c.mu.Lock()
defer c.mu.Unlock()
return c.count
}
*/
func worker(ch <-chan int, workerNumber int, wg *sync.WaitGroup) {
defer wg.Done()
for item := range ch {
fmt.Printf("workerNumber=%d, item=%d\n", workerNumber, item)
}
}
func main() {
wg := sync.WaitGroup{}
//counter := &Counter{}
taskCount := 10
workerCount := 3
ch := make(chan int, taskCount)
for i := 1; i <= workerCount; i++ {
wg.Add(1)
go worker(ch, i, &wg)
}
for j := 1; j < taskCount; j++ {
ch <- j
}
// close needed here before waitgroup
close(ch)
wg.Wait()
fmt.Println("All tasks have been processed.")
//fmt.Printf("Final count = %d\n", counter.GetCount())
}
Output
workerNumber=3, item=1
workerNumber=3, item=4
workerNumber=3, item=5
workerNumber=3, item=6
workerNumber=3, item=7
workerNumber=3, item=8
workerNumber=3, item=9
workerNumber=1, item=2
workerNumber=2, item=3
Program exited.
Negative cases
if we do not close the channel at the end, we will seen traceback.
// close needed here
// close(ch)
workerNumber=3, item=1
workerNumber=3, item=2
workerNumber=3, item=3
workerNumber=3, item=4
workerNumber=3, item=6
workerNumber=3, item=8
workerNumber=3, item=9
workerNumber=2, item=7
workerNumber=1, item=5
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc0000a4f18?)
/usr/local/go-faketime/src/runtime/sema.go:71 +0x25
sync.(*WaitGroup).Wait(0xc0000061c0?)
/usr/local/go-faketime/src/sync/waitgroup.go:118 +0x48
main.main()
/tmp/sandbox2297926600/prog.go:57 +0xfa
goroutine 18 [chan receive]:
main.worker(0xc0000b0000, 0x1, 0x0?)
/tmp/sandbox2297926600/prog.go:32 +0xfc
created by main.main in goroutine 1
/tmp/sandbox2297926600/prog.go:47 +0x58
goroutine 19 [chan receive]:
main.worker(0xc0000b0000, 0x2, 0x0?)
/tmp/sandbox2297926600/prog.go:32 +0xfc
created by main.main in goroutine 1
/tmp/sandbox2297926600/prog.go:47 +0x58
goroutine 20 [chan receive]:
main.worker(0xc0000b0000, 0x3, 0x0?)
/tmp/sandbox2297926600/prog.go:32 +0xfc
created by main.main in goroutine 1
/tmp/sandbox2297926600/prog.go:47 +0x58
Program exited.
Leave a Reply