多線程的代價及上下文切換


多線程的代價

     使用多線程往往可以獲得更大的吞吐率和更短的響應時間,但是,使用 多線程不一定就比單線程程序跑的快,這取決於我們程序設計者的能力以及應用場景的不同。不要為了多線程而多線程,而應考慮具體的應用場景和開發實力,使用多線程就是希望能夠獲得更快的處理速度和利用閑置的處理能力,如果沒帶來任何好處還帶來了復雜性和一些定時炸彈,那還傻逼了嗎?只有在使用多線程給我們帶來的好處遠大於我們付出的代價時,才考慮使用多線程,有時候可能引入多線程帶來的性能提升抵不過多線程而引入的開銷,一個沒有經過良好並發設計得程序也可能比使用單線程還更慢。
 
多線程給我們帶來的代價
  • 設計更復雜
     多線程程序在訪問共享數據的時候往往需要我們很小心的處理,否則就會出現難以發現的BUG,一般地,多線程程序往往比單線程程序設計會更加復雜(盡管有些單線程處理程序可能比多線程程序要復雜),而且 錯誤很難重現(因為線程調度的無序性,某些bug的出現 依賴於某種特定的線程執行時序)。
  • 上下文切換的開銷
     線程是由CPU進行調度的,CPU的一個時間片內只執行一個線程上下文內的線程,當CPU由執行線程A切換到執行線程B的過程中會發生一些列的操作,這些操作主要有” 保存線程A的執行現場“然后” 載入線程B的執行現場”,這個過程稱之為“ 上下文切換(context switch)”,這個 上下文切換過程並不廉價,如果沒有必要,應該盡量減少上下文切換的發生。
  • 增加更多的資源消耗
     除了 CPU執行上下文切換的消耗以外,線程的執行還將有其他一些資源的消耗,比如: 內存同步的開銷(線程需要一些內存在維持線程本地棧,每個線程都有本地獨立的棧用以存儲線程專用數據), 上下文切換的開銷(前面已經講過), 線程創建和消亡的開銷,以及 調度的開銷(占用操作系統的一些資源來管理和協調線程) 我們可以創建100個線程讓他們什么都不做,看看他們消耗了多少內存。
 
上下文切換

     多數人認為使用多線程一定會比單線程執行速度快,但其實未必,因為多線程應用程序會帶來額外的開銷和競爭問題,他們都可能會拖慢系統的執行速度。這些因素包括:對IO設備的競爭,對鎖的競爭,以及CPU對線程執行上下文的頻繁切換等。
 
     目前流行的CPU在同一時間內只能運行一個線程,超線程的處理器(包括多核處理器)可以同一時間運行多個線程,linux將多核處理器當作多個單獨CPU來識別的。每個進程都會分到CPU的時間片來運行,當某個進程( 線程是輕量級進程,他們是可以並行運行的,並且共享地使用他們所屬進程的地址空間資源,比如:內存空間或其他資源)當進程用完時間片或者被另一個優先級更高的進程搶占的時候,CPU會將該進程備份到CPU的 運行隊列中,其他進程被調度在CPU上運行,這個進程切換的過程被稱作“上下文切換”,過多的上下文切換會造成系統很大的開銷。
 
     在Linux中可以使用vmstat來觀察上下文切換的次數,一般來說,空閑的系統,每秒上下文切換次數大概在1500以下。
 
引起上下文切換的原因
  1. 時間片用完,CPU正常調度下一個任務
  2. 被其他優先級更高的任務搶占
  3. 執行任務碰到IO阻塞,調度器掛起當前任務,切換執行下一個任務
  4. 用戶代碼主動掛起當前任務讓出CPU時間
  5. 多任務搶占資源,由於沒有搶到被掛起
  6. 硬件中斷
參考:
  1. Costs of Multithreading
  2. Context Switch
  3. Context Switch Definition
  4. 從Java視角理解系統結構(一)CPU上下文切換
  5. Futext


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM