以下是 10 个 Go 并发编程的小测验, 看看你能答对几道题?
- 1 Mutex
- package main
- import (
- "fmt"
- "sync"
- )
- var mu sync.Mutex
- var chain string
- func main() {
- chain = "main"
- A()
- fmt.Println(chain)
- }
- func A() {
- mu.Lock()
- defer mu.Lock()
- chain = chain + "--> A"
- B()
- }
- func B() {
- chain = chain + "--> B"
- C()
- }
- func C() {
- mu.Lock()
- defer mu.Lock()
- chain = chain + "--> C"
- }
- main --> A --> B --> C
- main
- 2 RWMutex
- package main
- import (
- "fmt"
- "sync"
- "time"
- )
- var mu sync.RWMutex
- var count int
- func main() {
- go A()
- time.Sleep(2 * time.Second)
- mu.Lock()
- defer mu.Unlock()
- count++
- fmt.Println(count)
- }
- func A() {
- mu.RLock()
- defer mu.RUnlock()
- B()
- }
- func B() {
- time.Sleep(5 * time.Second)
- C()
- }
- func C() {
- mu.RLock()
- defer mu.RUnlock()
- }
- 3 Waitgroup
- package main
- import (
- "sync"
- "time"
- )
- func main() {
- var wg sync.WaitGroup
- wg.Add(1)
- go func() {
- time.Sleep(time.Millisecond)
- wg.Done()
- wg.Add(1)
- }()
- wg.Wait()
- }
A: 不能编译
B: 无输出, 正常退出
C: 程序 hang 住
D: panic
4 双检查实现单例
- package doublecheck
- import (
- "sync"
- )
- type Once struct {
- m sync.Mutex
- done uint32
- }
- func (o *Once) Do(f func()) {
- if o.done ==1 {
- return
- }
- o.m.Lock()
- defer o.m.Unlock()
- if o.done ==0 {
- o.done =1
- f()
- }
- }
A: 不能编译
B: 可以编译, 正确实现了单例
C: 可以编译, 有并发问题, f 函数可能会被执行多次
D: 可以编译, 但是程序运行会 panic
- 5 Mutex
- package main
- import (
- "fmt"
- "sync"
- )
- type MyMutex struct {
- count int
- sync.Mutex
- }
- func main() {
- var mu MyMutex
- mu.Lock()
- var mu2 = mu
- mu.count++
- mu.Unlock()
- mu2.Lock()
- mu2.count++
- mu2.Unlock()
- fmt.Println(mu.count, mu2.count)
- }
- 1, 1 1, 2
- 6 Pool
- package main
- import (
- "bytes"
- "fmt"
- "runtime"
- "sync"
- "time"
- )
- var pool = sync.Pool{New: func() interface{} { return new(bytes.Buffer) }}
- func main() {
- go func() {
- for {
- processRequest(1 <<28) // 256MiB
- }
- }()
- for i :=0; i <1000; i++ {
- go func() {
- for {
- processRequest(1 <<10) // 1KiB
- }
- }()
- }
- var stats runtime.MemStats
- for i :=0; ; i++ {
- runtime.ReadMemStats(&stats)
- fmt.Printf("Cycle %d: %dB\n", i, stats.Alloc)
- time.Sleep(time.Second)
- runtime.GC()
- }
- }
- func processRequest(size int) {
- b := pool.Get().(*bytes.Buffer)
- time.Sleep(500 * time.Millisecond)
- b.Grow(size)
- pool.Put(b)
- time.Sleep(1 * time.Millisecond)
- }
A: 不能编译
B: 可以编译, 运行时正常, 内存稳定
C: 可以编译, 运行时内存可能暴涨
D: 可以编译, 运行时内存先暴涨, 但是过一会会回收掉
- 7 channel
- package main
- import (
- "fmt"
- "runtime"
- "time"
- )
- func main() {
- var ch chan int
- go func() {
- ch = make(chan int,1)
- ch <-1
- }()
- go func(ch chan int) {
- time.Sleep(time.Second)
- <-ch
- }(ch)
- c := time.Tick(1 * time.Second)
- for range c {
- fmt.Printf("#goroutines: %d\n", runtime.NumGoroutine())
- }
- }
- #goroutines: 1
- #goroutines: 2
- 8 channel
- package main
- import "fmt"
- func main() {
- var ch chan int
- var count int
- go func() {
- ch <-1
- }()
- go func() {
- count++
- close(ch)
- }()
- <-ch
- fmt.Println(count)
- }
- 9 Map
- package main
- import (
- "fmt"
- "sync"
- )
- func main() {
- var m sync.Map
- m.LoadOrStore("a",1)
- m.Delete("a")
- fmt.Println(m.Len())
- }
- 10 happens before
- package main
- var c = make(chan int)
- var a int
- func f() {
- a =1
- <-c
- }
- func main() {
- go f()
- c <-0
- print(a)
- }
来源: http://www.tuicool.com/articles/EZJv63V