以下是12个Go并发编程的小测验,看看你能答对几道题? (持续增加中)
1 Mutex
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| 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.Unlock() chain = chain + " --> A" B() } func B() { chain = chain + " --> B" C() } func C() { mu.Lock() defer mu.Unlock() chain = chain + " --> C" }
|
- A: 不能编译
- B: 输出
main --> A --> B --> C
- C: 输出
main
- D: panic
2 RWMutex
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| 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() }
|
- A: 不能编译
- B: 输出
1
- C: 程序hang住
- D: panic
3 Waitgroup
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 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 双检查实现单例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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: 可以编译,不正确的单例实现
- D: 可以编译,但是程序运行会panic
5 Mutex
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| 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) }
|
- A: 不能编译
- B: 输出
1, 1
- C: 输出
1, 2
- D: panic
6 Pool
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| 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) } }() for i := 0; i < 1000; i++ { go func() { for { processRequest(1 << 10) } }() } 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 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()) } }
|
- A: 不能编译
- B: 一段时间后总是输出
#goroutines: 1
- C: 一段时间后总是输出
#goroutines: 2
- D: panic
8 channel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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) }
|
- A: 不能编译
- B: 输出
1
- C: 输出
0
- D: panic
9 Map
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package main import ( "fmt" "sync" ) func main() { var m sync.Map m.LoadOrStore("a", 1) m.Delete("a") fmt.Println(m.Len()) }
|
- A: 不能编译
- B: 输出
1
- C: 输出
0
- D: panic
10 happens before
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package main var c = make(chan int) var a int func f() { a = 1 <-c } func main() { go f() c <- 0 print(a) }
|
- A: 不能编译
- B: 输出
1
- C: 输出
0
- D: panic
11 自定义Map
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| package main import "sync" type Map struct { m map[int]int sync.Mutex } func (m *Map) Get(key int) (int, bool) { m.Lock() defer m.Unlock() i, ok := m.m[key] return i, ok } func (m *Map) Put(key, value int) { m.Lock() defer m.Unlock() m.m[key] = value } func (m *Map) Len() int { return len(m.m) } func main() { var wg sync.WaitGroup wg.Add(2) m := Map{m: make(map[int]int)} go func() { for i := 0; i < 10000000; i++ { m.Put(i, i) } wg.Done() }() go func() { for i := 0; i < 10000000; i++ { m.Len() } wg.Done() }() wg.Wait() }
|
go run quiz.go
运行。
- A: 不能编译
- B: 可运行,无并发问题
- C: 可运行,有并发问题
- D: panic
12 slice
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package main import ( "fmt" "sync" ) func main() { var wg sync.WaitGroup wg.Add(2) var ints = make([]int, 0, 1000) go func() { for i := 0; i < 1000; i++ { ints = append(ints, i) } wg.Done() }() go func() { for i := 0; i < 1000; i++ { ints = append(ints, i) } wg.Done() }() wg.Wait() fmt.Println(len(ints)) }
|
- A: 不能编译
- B: 输出
2000
- C: 输出可能不是
2000
- D: panic
13 goroutine
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| package main import ( "fmt" "sync" "time" ) type T struct { V int } func (t *T) Incr(wg *sync.WaitGroup) { t.V++ wg.Done() } func (t *T) Print() { time.Sleep(1e9) fmt.Print(t.V) } func main() { var wg sync.WaitGroup wg.Add(10) var ts = make([]T, 10) for i := 0; i < 10; i++ { ts[i] = T{i} } for _, t := range ts { go t.Incr(&wg) } wg.Wait() for _, t := range ts { go t.Print() } time.Sleep(5 * time.Second) }
|
- A: 输出
12345678910
- B: 输出
0123456789
- C: 输出
9999999999
- D: 输出
10101010101010101010
1. D
2. D
3. D
4. C
5. D
6. C
7. C
8. D
9. A
10. B
11. C
12. C
13. C
代码: go concurrency quiz