<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                題目來源:[Go 并發編程小測驗: 你能答對幾道題?](https://colobu.com/2019/04/28/go-concurrency-quizzes/) ### 1 Mutex ~~~go 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 ~~~go 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 ~~~go 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 雙檢查實現單例 ~~~go 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 ~~~go 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 ~~~go 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 ~~~go 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 ~~~go 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 ~~~go 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 ~~~go 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 ## 答案 ### 1\. D 會產生死鎖`panic`,因為`Mutex`是互斥鎖。 ### 2\. D 會產生死鎖`panic`,根據`sync/rwmutex.go`中注釋可以知道,讀寫鎖當有一個協程在等待寫鎖時,其他協程是不能獲得讀鎖的,而在`A`和`C`中同一個調用鏈中間需要讓出讀鎖,讓寫鎖優先獲取,而`A`的讀鎖又要求`C`調用完成,因此死鎖。 ### 3\. D `WaitGroup`在調用`Wait`之后是不能再調用`Add`方法的。 ### 4\. C 在多核 CPU 中,因為 CPU 緩存會導致多個核心中變量值不同步。 ### 5\. D 加鎖后復制變量,會將鎖的狀態也復制,所以`mu1`其實是已經加鎖狀態,再加鎖會死鎖。 ### 6\. C 個人理解,在單核 CPU 中,內存可能會穩定在`256MB`,如果是多核可能會暴漲。 ### 7\. C 因為`ch`未初始化,寫和讀都會阻塞,之后被第一個協程重新賦值,導致寫的`ch`都阻塞。 ### 8\. D `ch`未有被初始化,關閉時會報錯。 ### 9\. A `sync.Map`沒有`Len`方法。 ### 10\. B `c <- 0`會阻塞依賴于`f()`的執行。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看