<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                > # 進程,線程,協程 - **進程**:操作系統中資源分配的基本單位,具有獨立的地址空間, 上下文切換開銷大,適合需要隔離性和獨立性高的任務 - **線程**:進程中的執行單元,同一進程的線程共享內存和資源,適合需要大量并發且能夠共享資源的任務 - **協程**:比線程更輕量級的執行單元,由用戶態調度管理。協程的調度由程序自行控制,性能開銷更低,適合大量并發場景。 https://juejin.cn/post/7311893415151468584 > # GMP 原理和調度 - [GMP模型](https://go.cyub.vip/gmp/gmp-model/) - G是goroutine,M是線程,P是處理器。 P負責調度goroutine到線程上,維護了一個本地隊列,存儲了所有需要它來調度的G - P 的數量通常與邏輯 CPU 數量相等,可以通過 `runtime.GOMAXPROCS` 來調整。P 的數量越多,并發能力越強,但也會導致調度開銷增加 - `runtime.Gosched()` 可以主動讓出執行權 - 當創建新的 Goroutine 時,它通常被加入到當前 P 的本地隊列中。如果當前 P 的本地隊列已滿(如超過 256 個 Goroutine),部分 Goroutine 會被移至全局隊列 - P 先嘗試從本地隊列中獲取 Goroutine。如果本地隊列為空,P 會嘗試從全局隊列中獲取 Goroutine。如果全局隊列也為空,P 會從其他 P 的本地隊列中“竊取” Goroutine 執行(竊取 Goroutine 時,通常會竊取一半數量的 Goroutine) - M 執行一個 G 時,必須綁定一個 P。如果 M 因阻塞操作(如系統調用)而無法繼續執行,P 會解除與 M 的綁定,尋找另一個可用的 M 執行其他 G。原 M 完成阻塞操作后,將試圖重新獲取一個 P 繼續工作 > # 協程的調度不是隨機的 - Go 協程調度**不是隨機的**,但它也**不是按順序**的。它是一種基于信號的搶占式、工作竊取的調度模型 - 調度器的目的是在多個協程之間公平分配 CPU 資源,并在必要時暫停某些協程,讓其他協程有機會運行 ~~~ package main import ( "fmt" "time" ) func main() { ch := make(chan struct{}) for i := 0; i < 10; i++ { go func(num int) { for { <-ch fmt.Println(num) } }(i) time.Sleep(time.Millisecond) } time.Sleep(time.Second) for j := 0; j < 10; j++ { ch <- struct{}{} //**不加 `time.Sleep(time.Millisecond)`** 時,多個 Goroutine 幾乎同時啟動,調度器會隨機選擇哪個 Goroutine 先得到 CPU,因此打印順序不確定。 //**加了 `time.Sleep(time.Millisecond)`** 時,每個 Goroutine 啟動后,主協程會休眠 1 毫秒。這個時間足夠讓調度器有機會依次啟動每個 Goroutine,導致它們的打印順序更加有序 //time.Sleep(time.Millisecond) 改變輸出結果 } time.Sleep(time.Minute) } ~~~ > # CSP 模型 * **CSP**(Communicating Sequential Processes,通信順序進程) 是一種并發編程模型,其核心理念是**不要通過共享內存來通信,而要通過通信來實現內存共享**。 * 在 Go 語言中,CSP 模型主要通過 **Goroutine** 和 **Channel** 來實現。多個 Goroutine 之間的通信通常使用 **Channel**,從而避免了共享內存導致的并發問題。 > # 協程 (捕獲異常 和 協程池) - 直接用go關鍵字開協程,不捕獲異常的話, 如果出現異常,會導致整個程序結束 - Go 語言中的 **Goroutine** 相較于系統線程來說非常輕量級,其初始棧大小僅為 **2KB**。然而,在高并發場景下,大量的 Goroutine 被頻繁創建和銷毀,可能會對性能產生負面影響,并增加 **GC(垃圾回收)** 的壓力。 - 為了減少 Goroutine 的創建和銷毀所帶來的性能損耗,建議充分 **復用 Goroutine**。通過使用 **Goroutine 池** 或者其他方式來復用已經存在的 Goroutine,可以有效地降低系統的開銷 - goroutine.go ~~~ package main import ( "fmt" ) // WorkerPool 定義一個工作池結構體 type WorkerPool struct { maxWorkers int taskQueue chan func() } // NewWorkerPool 創建一個新的工作池 func NewWorkerPool(maxWorkers int) *WorkerPool { return &WorkerPool{ maxWorkers: maxWorkers, taskQueue: make(chan func()), } } // Start 啟動工作池 func (wp *WorkerPool) Start() { for i := 0; i < wp.maxWorkers; i++ { go wp.worker() } } // worker 執行任務的工作者 goroutine func (wp *WorkerPool) worker() { for task := range wp.taskQueue { safeExecute(task) } } // safeExecute 安全執行任務,捕獲異常 func safeExecute(task func()) { defer func() { if r := recover(); r != nil { fmt.Println("Recovered from panic:", r) } }() task() } // Submit 提交任務到工作池 func (wp *WorkerPool) Submit(task func()) { wp.taskQueue <- task } ~~~ - main.go ~~~ package main import ( "fmt" "time" ) var pool *WorkerPool func init() { pool = NewWorkerPool(20) pool.Start() } func SafeGo(f func()) { pool.Submit(f) } func main() { for i := 0; i < 10; i++ { SafeGo(func(num int) func() { return func() { fmt.Println("A", num) } }(i)) } for i := 0; i < 10; i++ { SafeGo(func(num int) func() { return func() { fmt.Println("B", num) } }(i)) } time.Sleep(time.Second * 3) } ~~~
                  <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>

                              哎呀哎呀视频在线观看