C#.NET面試題匯總系列四:多線程


0. 參考文檔

1. 描述線程與進程的區別?

線程(Thread)與進程(Process)二者都定義了某種邊界,不同的是進程定義的是應用程序與應用程序之間的邊界,不同的進程之間不能共享代碼和數據空間,而線程定義的是代碼執行堆棧和執行上下文的邊界

一個進程可以包括若干個線程,同時創建多個線程來完成某項任務,便是多線程

2. 什么是互斥?

當多個線程訪問同一個全局變量,或者同一個資源(比如打印機)的時候,需要進行線程間的互斥操作來保證訪問的安全性

3. Task狀態機的實現和工作機制是什么?

CPS全稱是Continuation Passing Style,在.NET中,它會自動編譯為:

  1. 將所有引用的局部變量做成閉包,放到一個隱藏的狀態機的類中
  2. 將所有的await展開成一個狀態號,有幾個await就有幾個狀態號
  3. 每次執行完一個狀態,都重復回調狀態機的MoveNext方法,同時指定下一個狀態號
  4. MoveNext方法還需處理線程和異常等問題

4. await的作用和原理,並說明和GetResult()有什么區別?

從狀態機的角度出發,await的本質是調用Task.GetAwaiter()的UnsafeOnCompleted(Action)回調,並指定下一個狀態號

從多線程的角度出發,如果await的Task需要在新的線程上執行,該狀態機的MoveNext()方法會立即返回,此時,主線程被釋放出來了,然后在UnsafeOnCompleted回調的action指定的線程上下文中繼續MoveNext()和下一個狀態的代碼

而相比之下,GetResult()就是在當前線程上立即等待Task的完成,在Task完成前,當前線程不會釋放

注意:Task也可能不一定在新的線程上執行,此時用GetResult()或者await就只有會不會創建狀態機的區別了

5. Task和Thread有區別嗎?

Task和Thread都能創建用多線程的方式執行代碼,但它們有較大的區別

Task較新,發布於.NET 4.5,能結合新的async/await代碼模型寫代碼,它不止能創建新線程,還能使用線程池(默認)、單線程等方式編程,在UI編程領域,Task還能自動返回UI線程上下文,還提供了許多便利API以管理多個Task

6. 多線程有什么用?

發揮多核CPU的優勢,防止阻塞

7. 說說常用的鎖,lock是一種什么樣的鎖?

常用的如 SemaphoreSlim、ManualResetEventSlim、Monitor、ReadWriteLockSlim

lock是一個混合鎖,其實質是 Monitor

8. lock為什么要鎖定一個參數(可否為值類型?)參數有什么要求?

lock的鎖對象要求為一個引用類型,可以鎖定值類型,但值類型會被裝箱,每次裝箱后的對象都不一樣,會導致鎖定無效

對於lock鎖,鎖定的這個對象參數才是關鍵,這個參數的同步索引塊指針會指向一個真正的鎖(同步塊),這個鎖(同步塊)會被復用

9. 多線程和異步的區別和聯系?

多線程是實現異步的主要方式之一,異步並不等同於多線程

實現異步的方式還有很多,比如利用硬件的特性、使用進程或纖程等

在.NET中就有很多的異步編程支持,比如很多地方都有Begin、End 的方法,就是一種異步編程支持,內部有些是利用多線程,有些是利用硬件的特性來實現的異步編程

10. 線程池的優點和不足?

優點:減小線程創建和銷毀的開銷,可以復用線程,也從而減少了線程上下文切換的性能損失,在GC回收時,較少的線程更有利於GC的回收效率

缺點:線程池無法對一個線程有更多的精確的控制,如了解其運行狀態等;不能設置線程的優先級;加入到線程池的任務(方法)不能有返回值;對於需要長期運行的任務就不適合線程池

11. Mutex和lock有什么不同?一般用哪一種比較好?

Mutex是一個基於內核模式的互斥鎖,支持鎖的遞歸調用

Lock是一個混合鎖,一般建議使用Lock更好,因為lock的性能更好

12. 如何實現線程間通信?

最簡單的就是定義靜態變量,然后在各個線程之間通過lock來訪問或修改變量

其次是利用線程上下文


免責聲明!

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



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