Go并发编程小测验: 你能答对几道题?

1 Mutex
 1 package main
 2 import (
 3    "fmt"
 4    "sync"
 5)
 6 var mu sync.Mutex
 7 var chain string
 8 func main() {
 9    chain = "main"
10    A()
11    fmt.Println(chain)
12}
13 func A() {
14    mu.Lock()
15    defer mu.Unlock()
16    chain = chain + " --> A"
17    B()
18}
19 func B() {
20    chain = chain + " --> B"
21    C()
22}
23 func C() {
24    mu.Lock()
25    defer mu.Unlock()
26    chain = chain + " --> C"
27}
  • A: 不能编译
  • B: 输出 main --> A --> B --> C
  • C: 输出 main
  • D: panic

2 RWMutex

 1 package main
 2 import (
 3    "fmt"
 4    "sync"
 5    "time"
 6)
 7 var mu sync.RWMutex
 8 var count int
 9 func main() {
10    go A()
11    time.Sleep(2 * time.Second)
12    mu.Lock()
13    defer mu.Unlock()
14    count++
15    fmt.Println(count)
16}
17 func A() {
18    mu.RLock()
19    defer mu.RUnlock()
20    B()
21}
22 func B() {
23    time.Sleep(5 * time.Second)
24    C()
25}
26 func C() {
27    mu.RLock()
28    defer mu.RUnlock()
29}
  • A: 不能编译
  • B: 输出 1
  • C: 程序hang住
  • D: panic

3 Waitgroup

 1 package main
 2 import (
 3    "sync"
 4    "time"
 5)
 6 func main() {
 7    var wg sync.WaitGroup
 8    wg.Add(1)
 9    go func() {
10        time.Sleep(time.Millisecond)
11        wg.Done()
12        wg.Add(1)
13    }()
14    wg.Wait()
15 }
  • A: 不能编译
  • B: 无输出,正常退出
  • C: 程序hang住
  • D: panic

4 双检查实现单例

 1 package doublecheck
 2 import (
 3    "sync"
 4)
 5 type Once struct {
 6    m    sync.Mutex
 7    done uint32
 8 }
 9 func (o *Once) Do(f func()) {
10    if o.done == 1 {
11        return
12    }
13    o.m.Lock()
14    defer o.m.Unlock()
15    if o.done == 0 {
16        o.done = 1
17        f()
18    }
19 }
  • A: 不能编译
  • B: 可以编译,正确实现了单例
  • C: 可以编译,有并发问题,f函数可能会被执行多次
  • D: 可以编译,但是程序运行会panic

5 Mutex

 1 package main
 2 import (
 3    "fmt"
 4    "sync"
 5 )
 6 type MyMutex struct {
 7    count int
 8    sync.Mutex
 9 }
10 func main() {
11    var mu MyMutex
12    mu.Lock()
13    var mu2 = mu
14    mu.count++
15    mu.Unlock()
16    mu2.Lock()
17    mu2.count++
18    mu2.Unlock()
19    fmt.Println(mu.count, mu2.count)
20 }
  • A: 不能编译
  • B: 输出 1, 1
  • C: 输出 1, 2
  • D: panic

6 Pool

 1 package main
 2 import (
 3    "bytes"
 4    "fmt"
 5    "runtime"
 6    "sync"
 7    "time"
 8)
 9 var pool = sync.Pool{New: func() interface{} { return new(bytes.Buffer) }}
10 func main() {
11    go func() {
12        for {
13            processRequest(1 << 28) // 256MiB
14        }
15    }()
16    for i := 0; i < 1000; i++ {
17        go func() {
18            for {
19                processRequest(1 << 10) // 1KiB
20            }
21        }()
22    }
23    var stats runtime.MemStats
24    for i := 0; ; i++ {
25        runtime.ReadMemStats(&stats)
26        fmt.Printf("Cycle %d: %dB\n", i, stats.Alloc)
27        time.Sleep(time.Second)
28        runtime.GC()
29    }
30}
31 func processRequest(size int) {
32    b := pool.Get().(*bytes.Buffer)
33    time.Sleep(500 * time.Millisecond)
34    b.Grow(size)
35    pool.Put(b)
36    time.Sleep(1 * time.Millisecond)
37 }
  • A: 不能编译
  • B: 可以编译,运行时正常,内存稳定
  • C: 可以编译,运行时内存可能暴涨
  • D: 可以编译,运行时内存先暴涨,但是过一会会回收掉

7 channel

 1 package main
 2 import (
 3    "fmt"
 4    "runtime"
 5    "time"
 6)
 7 func main() {
 8    var ch chan int
 9    go func() {
10        ch = make(chan int, 1)
11        ch <- 1
12    }()
13    go func(ch chan int) {
14        time.Sleep(time.Second)
15        <-ch
16    }(ch)
17    c := time.Tick(1 * time.Second)
18    for range c {
19        fmt.Printf("#goroutines: %d\n", runtime.NumGoroutine())
20    }
21}
  • A: 不能编译
  • B: 一段时间后总是输出 #goroutines: 1
  • C: 一段时间后总是输出 #goroutines: 2
  • D: panic

8 channel

 1 package main
 2 import "fmt"
 3 func main() {
 4    var ch chan int
 5    var count int
 6    go func() {
 7        ch <- 1
 8    }()
 9    go func() {
10        count++
11        close(ch)
12    }()
13    <-ch
14    fmt.Println(count)
15}
  • A: 不能编译
  • B: 输出 1
  • C: 输出 0
  • D: panic

9 Map

 1 package main
 2 import (
 3    "fmt"
 4    "sync"
 5)
 6 func main() {
 7    var m sync.Map
 8    m.LoadOrStore("a", 1)
 9    m.Delete("a")
10    fmt.Println(m.Len())
11}
  • A: 不能编译
  • B: 输出 1
  • C: 输出 0
  • D: panic

10 happens before

 1 package main
 2 var c = make(chan int)
 3 var a int
 4 func f() {
 5    a = 1
 6    <-c
 7}
 8 func main() {
 9    go f()
10    c <- 0
11    print(a)
12}
  • A: 不能编译
  • B: 输出 1
  • C: 输出 0
  • D: panic

11 自定义Map

 1 package main
 2 import "sync"
 3 type Map struct {
 4    m map[int]int
 5    sync.Mutex
 6}
 7 func (m *Map) Get(key int) (int, bool) {
 8    m.Lock()
 9    defer m.Unlock()
10    i, ok := m.m[key]
11    return i, ok
12}
13 func (m *Map) Put(key, value int) {
14    m.Lock()
15    defer m.Unlock()
16    m.m[key] = value
17}
18 func (m *Map) Len() int {
19    return len(m.m)
20}
21 func main() {
22    var wg sync.WaitGroup
23    wg.Add(2)
24    m := Map{m: make(map[int]int)}
25    go func() {
26        for i := 0; i < 10000000; i++ {
27            m.Put(i, i)
28        }
29        wg.Done()
30    }()
31    go func() {
32        for i := 0; i < 10000000; i++ {
33            m.Len()
34        }
35        wg.Done()
36    }()
37    wg.Wait()
38}

go run quiz.go运行。

  • A: 不能编译
  • B: 可运行,无并发问题
  • C: 可运行,有并发问题
  • D: panic

12 Slice

 1 package main
 2 import (
 3    "fmt"
 4    "sync"
 5)
 6 func main() {
 7    var wg sync.WaitGroup
 8    wg.Add(2)
 9    var ints = make([]int, 0, 1000)
10    go func() {
11        for i := 0; i < 1000; i++ {
12            ints = append(ints, i)
13        }
14        wg.Done()
15    }()
16    go func() {
17        for i := 0; i < 1000; i++ {
18            ints = append(ints, i)
19        }
20        wg.Done()
21    }()
22    wg.Wait()
23    fmt.Println(len(ints))
24}
  • A: 不能编译
  • B: 输出2000
  • C: 输出可能不是2000
  • D: panic

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2019-05-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券