32
Go并发编程小测验: 你能答对几道题?
source link: https://colobu.com/2019/04/28/go-concurrency-quizzes/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
以下是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) }
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK