1、說說概念面試
1、進程(process)編程
狹義定義:進程就是一段程序的執行過程。安全
廣義定義:進程是一個具備必定獨立功能的程序關於某個數據集合的一次運行活動。它是操做系統動態執行的基本單元,在傳統的操做系統中,進程既是基本的分配單元,也是基本的執行單元。多線程
簡單的來說進程的概念主要有兩點:第一,進程是一個實體。每個進程都有它本身的地址空間,通常狀況下,包括文本區域(text region)、數據區域(data region)和堆棧(stack region)。文本區域存儲處理器執行的代碼;數據區域存儲變量和進程執行期間使用的動態分配的內存;堆棧區域存儲着活動過程調用的指令和本地變量。第二,進程是一個「執行中的程序」。程序是一個沒有生命的實體,只有處理器賦予程序生命時,它才能成爲一個活動的實體,咱們稱其爲進程。併發
進程狀態:進程有三個狀態,就緒、運行和阻塞。就緒狀態其實就是獲取了出cpu外的全部資源,只要處理器分配資源就能夠立刻執行。就緒狀態有排隊序列什麼的,排隊原則再也不贅述。運行態就是得到了處理器分配的資源,程序開始執行。阻塞態,當程序條件不夠時候,須要等待條件知足時候才能執行,如等待i/o操做時候,此刻的狀態就叫阻塞態。異步
2、程序ide
提及進程,就不得不說下程序。先看定義:程序是指令和數據的有序集合,其自己沒有任何運行的含義,是一個靜態的概念。而進程則是在處理機上的一次執行過程,它是一個動態的概念。這個不難理解,其實進程是包含程序的,進程的執行離不開程序,進程中的文本區域就是代碼區,也就是程序。spa
3、線程操作系統
一般在一個進程中能夠包含若干個線程,固然一個進程中至少有一個線程,否則沒有存在的意義。線程能夠利用進程所擁有的資源,在引入線程的操做系統中,一般都是把進程做爲分配資源的基本單位,而把線程做爲獨立運行和獨立調度的基本單位,因爲線程比進程更小,基本上不擁有系統資源,故對它的調度所付出的開銷就會小得多,能更高效的提升系統多個程序間併發執行的程度。線程
4、多線程
在一個程序中,這些獨立運行的程序片斷叫做「線程」(Thread),利用它編程的概念就叫做「多線程處理」。多線程是爲了同步完成多項任務,不是爲了提升運行效率,而是爲了提升資源使用效率來提升系統的效率。線程是在同一時間須要完成多項任務的時候實現的。
最簡單的比喻多線程就像火車的每一節車箱,而進程則是火車。車箱離開火車是沒法跑動的,同理火車也不可能只有一節車箱。多線程的出現就是爲了提升效率。
2、說說區別
1、進程與線程的區別:
進程和線程的主要差異在於它們是不一樣的操做系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不一樣執行路徑。線程有本身的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,因此多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行而且又要共享某些變量的併發操做,只能用線程,不能用進程。
1) 簡而言之,一個程序至少有一個進程,一個進程至少有一個線程.
2) 線程的劃分尺度小於進程,使得多線程程序的併發性高。
3) 另外,進程在執行過程當中擁有獨立的內存單元,而多個線程共享內存,從而極大地提升了程序的運行效率。
4) 線程在執行過程當中與進程仍是有區別的。每一個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。可是線程不可以獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
5) 從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分能夠同時執行。但操做系統並無將多個線程看作多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。
3、說說優缺點
線程和進程在使用上各有優缺點:線程執行開銷小,但不利於資源的管理和保護;而進程正相反。同時,線程適合於在SMP(多核處理機)機器上運行,而進程則能夠跨機器遷移。
4、總結
入職第一天閒的無聊,參考下別人的總結本身也簡單總結了下。知道以上的基本面試夠用了,至於進程、線程的細節,底層構成,調度等問題是操做系統的東西。我就不詳述了。
5、實例
一、多線程寫日誌,涉及到單例模式,異步寫
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Thread t1 = new Thread(Working); t1.Name = "Thread1"; Thread t2 = new Thread(Working); t2.Name = "Thread2"; Thread t3 = new Thread(Working); t3.Name = "Thread3"; // 依次啓動3個線程。 t1.Start(); t2.Start(); t3.Start(); Console.ReadKey(); } // 每一個線程都同時在工做 static void Working() { // 模擬1000次寫日誌操做 for (int i = 0; i < 1000; i++) { // 異步寫文件 logger.Write(Thread.CurrentThread.Name + " writes a log: " + i + ", on " + DateTime.Now.ToString() + ".\n"); }// 作一些其它的事件 for (int i = 0; i < 100; i++) { } } } public class logger { private Queue<Action> _queue; //寫日誌線程 private Thread _loggingThread; //信號器 private ManualResetEvent _hasNew; // 使用單例模式,保持一個Logger對象 private static readonly logger _logger = new logger(); private static logger GetInstance() { /* 不安全代碼 lock (locker) { if (_logger == null) { _logger = new Logger(); } }*/ return _logger; } private logger() { _queue = new Queue<Action>(); _hasNew = new ManualResetEvent(false); _loggingThread = new Thread(Process); _loggingThread.IsBackground = true; _loggingThread.Start(); } private void Process() { while (true) { //等待信號,阻塞線程 _hasNew.WaitOne(); //接收到信號,信號關閉,重置 _hasNew.Reset(); Thread.Sleep(100); Queue<Action> queueCopy; lock (_queue) { queueCopy = new Queue<Action>(_queue); _queue.Clear(); } foreach (var action in queueCopy) { action(); } } } private void WeiteLog(string content) { lock (_queue) { _queue.Enqueue(() => File.AppendAllText("log.txt", content)); } _hasNew.Set(); } public static void Write(string content) { Task.Run(() => GetInstance().WeiteLog(content)); } } }