<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 功能強大 支持多語言、二開方便! 廣告
                ### sync包 go語言多線程,子線程運行時間大于主線程時,主線程運行完畢就會關閉程序,屆時子線程沒運行完。 示例代碼:創建一個主線程和一個test的子線程,主線程和子線程都使用for循環輸出i,子線程時間間隔為3秒,主線程為1秒。子線程執行時間大于主線程 ``` package main import ( "fmt" "time" ) // 子進程函數 func test() { for i := 0; i < 10; i++ { fmt.Println("子線程輸出", i) // 這里加一個子線程堵塞時間間隔 3秒 比主線程少1秒 time.Sleep(time.Second * 3) } } // main函數的是主線程 func main() { // 如果不加關鍵詞 go 就會順序執行 先執行 test函數的 // 加關鍵詞 go 但是test函數沒有執行, 是因為主線程運行太快直接結束關閉了程序 go test() for i := 0; i < 10; i++ { fmt.Println("主線程輸出", i) // 這里個主線程加一個時間堵塞,但是時間比子線程少 time.Sleep(time.Second) } // 所以 需要加 一個休眠時間堵塞一下 time.Sleep(time.Second) fmt.Println("主線程結束") } //總結: // go語言多線程 需要加時間堵塞 才能運行 // 子線程運行時間大于主線程時,主線程運行完畢就會關閉程序,屆時子線程沒運行完 ``` 基于上面的示例代碼,使用sync包里面**sync.WaitGroup** (等待組) 示例代碼:和上面一樣,這里使用sync包里面的等待組sync.WaitGroup 第一步創建全局變量,wg類型sync.WaitGroup 第二步使用Add()函數協程計數器加1 第三步,子進程結束使用Done()函數協程計數器減1 第四步主進程使用Wait()函數等待子進程 ``` package main import ( "fmt" "sync" "time" ) // 第一步 創建一個全局變量 wg 類型是sync.WaitGroup var wg sync.WaitGroup // 子進程函數 func test() { for i := 0; i < 10; i++ { fmt.Println("子線程輸出", i) time.Sleep(time.Second * 2) } // 第三步,子進程結束 使用sync包里面的 Done()函數 協程計數器加-1 wg.Done() } // main函數的是主線程 func main() { // 第二步,調用協程時,使用sync包里面的 Add()函數 協程計數器加1 wg.Add(1) go test() for i := 0; i < 10; i++ { fmt.Println("主線程輸出", i) time.Sleep(time.Second) } // 第四步,調用協程時,使用sync包里面的 Wait()函數 主線程等待子線程結束 wg.Wait() fmt.Println("主線程結束") } // 總結:這樣就會一直等到子線程直線完畢 程序才關閉 ``` ``` package main import ( "fmt" "sync" ) func main() { wg := sync.WaitGroup{} wg.Add(100) for i := 0; i < 100; i++ { go func(i int) { fmt.Println(i) wg.Done() }(i) } wg.Wait() } ``` 多個協程示例代碼 ``` package main import ( "fmt" "sync" "time" ) var wg sync.WaitGroup // 子進程函數 func test(num int) { for i := 0; i < 10; i++ { fmt.Println("線程", num, "輸出", i) // time.Sleep(time.Second * 2) 堵塞2秒 time.Sleep(time.Millisecond * 100) // 100毫秒 } wg.Done() } // main函數的是主線程 func main() { for i := 0; i < 3; i++ { wg.Add(1) go test(i) } for i := 0; i < 10; i++ { fmt.Println("主線程輸出", i) time.Sleep(time.Millisecond * 20) // 20毫秒 } wg.Wait() fmt.Println("主線程結束") } ``` 互斥鎖 **sync.Mutex** 加互斥鎖主要解決(編譯后)資源競爭的問題。比如多個線程搶占一個資源,例如多個協程讀取數據庫里面的一條內容。加了鎖之后,只有一個協程讀取,其他的等待它讀取完再執行操作。 示例代碼:創建變量j初始值為0,test函數執行一次,j就會遞增。如果多個進程同時使j遞增的話,就可能因為進程搶占資源報錯。但是加了互斥鎖之后,就會等一個協程執行完之后,再執行另外一個。就不會發生資源搶占而報錯。 ``` package main import ( "fmt" "sync" ) // 邏輯中使用的某個變量 var j = 0 // 與變量對應的使用互斥鎖 var mutex sync.Mutex // 等待組 var wg sync.WaitGroup // 子進程 func test() { // 邏輯開始加互斥鎖 mutex.Lock() // 邏輯遍歷遞增 j++ fmt.Println("邏輯變量", j) // 去邏輯鎖 mutex.Unlock() // 協程計數器減1 wg.Done() } //主進程 func main() { for i := 0; i < 10; i++ { // 協程計數器加1 wg.Add(1) go test() } // 等待子進程結束關閉程序 wg.Wait() } ``` 讀寫互斥鎖 **sync.RWMutex** 讀寫互斥鎖定,可以讓多個讀操作并發,同時讀取,但是對于寫操作是完全互斥的。也就是說當一個協程進行寫操作的時候,其他協程不能進行讀操作也不也能寫操作。 示例代碼:10個進程執行寫的操作,10個進程執行讀的操作,加上讀寫互斥鎖之后,寫的操作是互斥的,只能一個進程操作完,下個進程才能操作。讀的時候是并行的。 ``` package main import ( "fmt" "sync" "time" ) // 等待組 var wg sync.WaitGroup // 讀寫互斥鎖 var mutex sync.RWMutex // 寫操作的協程 func write() { // 加互斥鎖 mutex.Lock() fmt.Println("@@@執行寫操作") time.Sleep(time.Millisecond * 1000) //1000毫秒 // 去鎖 mutex.Unlock() wg.Done() } func read() { // 加讀寫互斥鎖 mutex.RLock() fmt.Println("執行讀操作$$$") time.Sleep(time.Millisecond * 1000) //1000毫秒 // 去鎖 mutex.RUnlock() wg.Done() } func main() { // 10個協程執行寫的操作 for i := 0; i < 10; i++ { wg.Add(1) go write() } // 10協程執行讀的操作 for i := 0; i < 10; i++ { wg.Add(1) go read() } wg.Wait() } ```
                  <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>

                              哎呀哎呀视频在线观看