<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 功能強大 支持多語言、二開方便! 廣告
                [TOC] # 簡介 如果使用用戶級線程,我們就不得不既是指令下達者,又是指令執行者。我們必須全權負責與用戶級線程有關的所有具體實現。 操作系統不但不會幫忙,還會要求我們的具體實現必須與它正確地對接,否則用戶級線程就無法被并發地,甚至正確地運行。畢竟我們編寫的所有代碼最終都需要通過操作系統才能在計算機上執行 不過別擔心,Go 語言不但有著獨特的并發編程模型,以及**用戶級線程 goroutine,還擁有強大的用于調度 goroutine、對接系統級線程的調度器。** 這個調度器是 Go 語言運行時系統的重要組成部分,它主要負責統籌調配 Go 并發編程模型中的三個主要元素,即:G(goroutine 的縮寫)、P(processor 的縮寫)和 M(machine 的縮寫) 其中的 M 指代的就是系統級線程。而 P 指的是一種可以承載若干個 G,且能夠使這些 G 適時地與 M 進行對接,并得到真正運行的中介。 從宏觀上說,G 和 M 由于 P 的存在可以呈現出多對多的關系。當一個正在與某個 M 對接并運行著的 G,需要因某個事件(比如等待 I/O 或鎖的解除)而暫停運行的時候,調度器總會及時地發現,并把這個 G 與那個 M 分離開,以釋放計算資源供那些等待運行的 G 使用。 而當一個 G 需要恢復運行的時候,調度器又會盡快地為它尋找空閑的計算資源(包括 M)并安排運行。另外,當 M 不夠用時,調度器會幫我們向操作系統申請新的系統級線程,而當某個 M 已無用時,調度器又會負責把它及時地銷毀掉。 正因為調度器幫助我們做了很多事,所以我們的 Go 程序才總是能高效地利用操作系統和計算機資源。程序中的所有 goroutine 也都會被充分地調度,其中的代碼也都會被并發地運行,即使這樣的 goroutine 有數以十萬計,也仍然可以如此 ![](https://box.kancloud.cn/d84ac493d31e465e2f9b099d82c0395d_1398x744.png) **一定要注意,go函數真正被執行的時間,總會與其所屬的go語句被執行的時間不同。當程序執行到一條go語句的時候,Go 語言的運行時系統,會先試圖從某個存放空閑的 G 的隊列中獲取一個 G(也就是 goroutine),它只有在找不到空閑 G 的情況下才會去創建一個新的 G** # 控制數量 用runtime.GOMAXPROCS(maxProcs)來控制P的數量 **控制協程的數量** 我們先創建一個通道,它的長度應該與我們手動啟用的 goroutine 的數量一致。在每個手動啟用的 goroutine 即將運行完畢的時候,我們都要向該通道發送一個值 ~~~ import ( "fmt" ) func main() { num := 10 sign := make(chan struct{}, num) for i := 0; i < num; i++ { go func() { fmt.Println(i) sign <- struct{}{} }() } for j := 0; j < num; j++ { <-sign } } ~~~ 其中有一個細節你需要注意。我在聲明通道sign的時候是以chan struct{}作為其類型的。其中的類型字面量struct{}有些類似于空接口類型interface{},它代表了既不包含任何字段也不擁有任何方法的空結構體類型。 注意,struct{}類型值的表示法只有一個,即:struct{}{}。并且,它占用的內存空間是0字節。確切地說,這個值在整個 Go 程序中永遠都只會存在一份。雖然我們可以無數次地使用這個值字面量,但是用到的卻都是同一個值
                  <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>

                              哎呀哎呀视频在线观看