● 請你說一下多進程、多線程,操做系統層面的差異和聯繫
參考回答:
進程:進程是一個具備必定獨立功能的程序在一個數據集上的一次動態執行的過程,是操做系統進行資源分配和調度的一個獨立單位,是應用程序運行的載體。進程是一種抽象的概念,歷來沒有統一的標準定義。進程通常由程序、數據集合和進程控制塊三部分組成。程序用於描述進程要完成的功能,是控制進程執行的指令集;數據集合是程序在執行時所須要的數據和工做區;程序控制塊(Program Control Block,簡稱PCB),包含進程的描述信息和控制信息,是進程存在的惟一標誌。java
線程:在早期的操做系統中並無線程的概念,進程是能擁有資源和獨立運行的最小單位,也是程序執行的最小單位。任務調度採用的是時間片輪轉的搶佔式調度方式,而進程是任務調度的最小單位,每一個進程有各自獨立的一塊內存,使得各個進程之間內存地址相互隔離。後來,隨着計算機的發展,對CPU的要求愈來愈高,進程之間的切換開銷較大,已經沒法知足愈來愈複雜的程序的要求了。因而就發明了線程,線程是程序執行中一個單一的順序控制流程,是程序執行流的最小單元,是處理器調度和分派的基本單位。一個進程能夠有一個或多個線程,各個線程之間共享程序的內存空間(也就是所在進程的內存空間)。一個標準的線程由線程ID、當前指令指針(PC)、寄存器和堆棧組成。而進程由內存空間(代碼、數據、進程空間、打開的文件)和一個或多個線程組成。程序員
差異:1.線程是程序執行的最小單位,而進程是操做系統分配資源的最小單位;2.一個進程由一個或多個線程組成,線程是一個進程中代碼的不一樣執行路線;3.進程之間相互獨立,但同一進程下的各個線程之間共享程序的內存空間(包括代碼段、數據集、堆等)及一些進程級的資源(如打開文件和信號),某進程內的線程在其它進程不可見;4.調度和切換:線程上下文切換比進程上下文切換要快得多。算法
聯繫:原則上一個CPU只能分配給一個進程,以便運行這個進程。一般使用的計算機中只有一個CPU,同時運行多個進程,就必須使用併發技術。一般採用時間片輪轉進程調度算法,在操做系統的管理下,全部正在運行的進程輪流使用CPU,每一個進程容許佔用CPU的時間很是短(好比10毫秒),這樣用戶根本感受不出來CPU是在輪流爲多個進程服務,就好象全部的進程都在不間斷地運行同樣。但實際上在任何一個時間內有且僅有一個進程佔有CPU。若是一臺計算機有多個CPU,狀況就不一樣了,若是進程數小於CPU數,則不一樣的進程能夠分配給不一樣的CPU來運行,這樣,多個進程就是真正同時運行的,這即是並行。但若是進程數大於CPU數,則仍然須要使用併發技術。在Windows中,進行CPU分配是以線程爲單位的,一個進程可能由多個線程組成。操做系統將CPU的時間片分配給多個線程,每一個線程在操做系統指定的時間片內完成(注意,這裏的多個線程是分屬於不一樣進程的).操做系統不斷的從一個線程的執行切換到另外一個線程的執行,如此往復,宏觀上看來,就好像是多個線程在一塊兒執行.因爲這多個線程分屬於不一樣的進程,就好像是多個進程在同時執行,這樣就實現了多任務。總線程數<=CPU數量時並行運行,總線程數>CPU數量時併發運行。並行運行的效率顯然高於併發運行,因此在多CPU的計算機中,多任務的效率比較高。可是,若是在多CPU計算機中只運行一個進程(線程),就不能發揮多CPU的優點。數據庫
● 請你說一下線程通訊的方法、線程的五種狀態
參考回答:
線程通訊的方法:編程
①同步:多個線程經過synchronized關鍵字這種方式來實現線程間的通訊。安全
②while輪詢的方式服務器
③wait/notify機制網絡
④管道通訊就是使用java.io.PipedInputStream 和 java.io.PipedOutputStream進行通訊多線程
線程的五種狀態:併發
1. 新建(NEW):新建立了一個線程對象。
2. 可運行(RUNNABLE):線程對象建立後,其餘線程(好比main線程)調用了該對象的start()方法。該狀態的線程位於可運行線程池中,等待被線程調度選中,獲取cpu 的使用權 。
3. 運行(RUNNING):可運行狀態(runnable)的線程得到了cpu 時間片(timeslice) ,執行程序代碼。
4. 阻塞(BLOCKED):阻塞狀態是指線程由於某種緣由放棄了cpu 使用權,也即讓出了cpu timeslice,暫時中止運行。直到線程進入可運行(runnable)狀態,纔有機會再次得到cpu timeslice 轉到運行(running)狀態。阻塞的狀況分三種:
(一). 等待阻塞:運行(running)的線程執行o.wait()方法,JVM會把該線程放入等待隊列(waitting queue)中。
(二). 同步阻塞:運行(running)的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池(lock pool)中。
(三). 其餘阻塞:運行(running)的線程執行Thread.sleep(long ms)或t.join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程從新轉入可運行(runnable)狀態。
5. 死亡(DEAD):線程run()、main() 方法執行結束,或者因異常退出了run()方法,則該線程結束生命週期。死亡的線程不可再次復生。
● 請你說一下虛擬內存
參考回答:
虛擬內存是計算機系統內存管理的一種技術。它使得應用程序認爲它擁有連續的可用的內存(一個連續完整的地址空間),而實際上,它一般是被分隔成多個物理內存碎片,還有部分暫時存儲在外部磁盤存儲器上,在須要時進行數據交換
● 請你說一下線程的同步和互斥以及應用常見
參考回答:
互斥:指在某一時刻指容許一個進程運行其中的程序片,具備排他性和惟一性。
對於線程A和線程B來說,在同一時刻,只容許一個線程對臨界資源進行操做,即當A進入臨界區對資源操做時,B就必須等待;當A執行完,退出臨界區後,B才能對臨界資源進行操做。
同步:指的是在互斥的基礎上,實現進程之間的有序訪問。假設現有線程A和線程B,線程A須要往緩衝區寫數據,線程B須要從緩衝區讀數據,但他們之間存在一種制約關係,即當線程A寫的時候,B不能來拿數據;B在拿數據的時候A不能往緩衝區寫,也就是說,只有當A寫完數據(或B取走數據),B才能來讀數據(或A才能往裏寫數據)。這種關係就是一種線程的同步關係。
應用常見:多線程編程中,不免會遇到多個線程同時訪問臨界資源的問題,若是不對其加以保護,那麼結果確定是不如預期的,所以須要線程同步與互斥。
● 請你說一下線程的五種狀態以及轉換
參考回答:
一、新生狀態
在程序中用構造方法(new操做符)建立一個新線程時,如new Thread(r),該線程就是建立狀態,此時它已經有了相應的內存空間和其它資源,可是尚未開始執行。
二、就緒狀態
新建線程對象後,調用該線程的start()方法就能夠啓動線程。當線程啓動時,線程進入就緒狀態(runnable)。因爲尚未分配CPU,線程將進入線程隊列排隊,等待 CPU 服務,這代表它已經具有了運行條件。當系統挑選一個等待執行的Thread對象後,它就會從等待執行狀態進入執行狀態。系統挑選的動做稱之爲「CPU調度"。一旦得到CPU線程就進入運行狀態並自動調用本身的run方法。
三、運行狀態
當就緒狀態的線程被調用並得到處理器資源時,線程就進入了運行狀態。此時,自動調用該線程對象的run()方法。run()方法定義了該線程的操做和功能。運行狀態中的線程執行本身的run方法中代碼。直到調用其餘方法或者發生阻塞而終止。
四、阻塞狀態
一個正在執行的線程在某些特殊狀況下,如被人爲掛起或須要執行耗時的輸入輸出操做時,suspend()、 wait()等方法,線程都將進入堵塞狀態。堵塞時,線程不能進入排隊隊列,只有當引發堵塞的緣由被消除後,線程轉入就緒狀態。重將讓出 CPU 並暫時停止本身的執行,進入堵塞狀態。在可執行狀態下,若是調用 sleep()、 新到就緒隊列中排隊等待,這時被CPU調度選中後會從原來中止的位置開始繼續執行。
五、死亡狀態
線程調用stop()方法、destory()方法或 run()方法執行結束後,線程即處於死亡狀態。處於死亡狀態的線程不具備繼續運行的能力。
● 請你說一說消息隊列、信號量的實現方式
參考回答:
消息隊列是消息的連接表,存儲在內核中,由消息隊列ID來標識。每一個隊列都有一個msgid_ds結構與其相關聯:
struct msgid_ds
{
struct ipc_perm msg_perm;
msgqnum_t msg_qnum; /* # of messages on queue */
msglen_t msg_qbytes; /* max # of bytes on queue */
pid_t msg_lspid; /* pid of last msgsnd() */
pid_t msg_lrpid; /* pid of last msgrcv() */
time_t msg_stime; /* last-msgsnd() time */
time_t msg_rtime; /* last-msgrcv() time */
time_t msg_ctime; /* last-change time */
...
};
此結構定義了隊列的當前狀態。msgget用於建立一個新隊列或打開一個現有隊列,msgsnd將消息添加到隊列的尾端(每一個消息包括一個長整型類型字段,一個非負的長度,實際的數據長度),msgrcv用於從隊列中取消息(並不必定要以先進先出次序取消息,能夠按消息的類型字段取消息)。
信號量是一個計數器,用於爲多個進程提供對共享對象的訪問。爲了正確地實現信號量,信號量的測試及加減1操做應當是原子操做,爲此,信號量一般是在內核中實現的。
經常使用的信號形式是二元信號量(binary semaphore)。它控制單個資源,其初始值爲1。可是,通常而言,信號量的初值也能夠是任意一個正值,代表有多少個共享單位可供共享。
內核爲每一個信號量集合維護着一個semid_ds結構:
struct semid_ds
{
struct ipc_perm sem_perm;
unsigned short sem_nsems; /* # of semaphores in set */
time_t sem_otime; /* last-semop() time */
time_t sem_ctime; /* last-change time */
...
};
每一個信號量由一個無名結構體表示,至少包含下列成員:
複製代碼
1 2 3 4 5 6 7 8 |
|
● 請你說一下進程和線程的區別
參考回答:
進程:是具備必定獨立功能的程序、它是系統進行資源分配和調度的一個獨立單位,重點在系統調度和單獨的單位,也就是說進程是能夠獨立運行的一段程序。
線程:是進程的一個實體,是CPU調度和分派的基本單位,比進程更小的能獨立運行的基本單位,線程本身基本上不擁有系統資源,在運行時,只是暫用一些計數器、寄存器和棧 。線程有本身的堆棧和局部變量,但線程之間沒有單獨的地址空間。
一個程序至少有一個進程,一個進程至少有一個線程。
● 請你說一下死鎖的概念、緣由、解決方法
參考回答:
一、死鎖是指在一組進程中的各個進程均佔有不會釋放的資源,但因互相申請被其餘進程所站用不會釋放的資源而處於的一種永久等待狀態。死鎖的四個必要條件:
• 互斥條件(Mutual exclusion):資源不能被共享,只能由一個進程使用。
• 請求與保持條件(Hold and wait):已經獲得資源的進程能夠再次申請新的資源。
• 非剝奪條件(No pre-emption):已經分配的資源不能從相應的進程中被強制地剝奪。
• 循環等待條件(Circular wait):系統中若干進程組成環路,該環路中每一個進程都在等待相鄰進程正佔用的資源。
java中產生死鎖可能性的最根本緣由是:1)是多個線程涉及到多個鎖,這些鎖存在着交叉,因此可能會致使了一個鎖依賴的閉環;2)默認的鎖申請操做是阻塞的。
如,線程在得到一個鎖L1的狀況下再去申請另一個鎖L2,也就是鎖L1想要包含了鎖L2,在得到了鎖L1,而且沒有釋放鎖L1的狀況下,又去申請得到鎖L2,這個是產生死鎖的最根本緣由。
二、避免死鎖:
• 方案一:破壞死鎖的循環等待條件。
• 方法二:破壞死鎖的請求與保持條件,使用lock的特性,爲獲取鎖操做設置超時時間。這樣不會死鎖(至少不會無盡的死鎖)
• 方法三:設置一個條件遍歷與一個鎖關聯。該方法只用一把鎖,沒有chopstick類,將競爭從對筷子的爭奪轉換成了對狀態的判斷。僅當左右鄰座都沒有進餐時才能夠進餐。提高了併發度。
● 請你說一下多線程
參考回答:
最開始,線程只是用於分配單個處理器的處理時間的一種工具。但假如操做系統自己支持多個處理器,那麼每一個線程均可分配給一個不一樣的處理器,真正進入「並行運算」狀態。從程序設計語言的角度看,多線程操做最有價值的特性之一就是程序員沒必要關心到底使用了多少個處理器。程序在邏輯意義上被分割爲數個線程;假如機器自己安裝了多個處理器,那麼程序會運行得更快,毋需做出任何特殊的調校。根據前面的論述,你們可能感受線程處理很是簡單。但必須注意一個問題:共享資源!若是有多個線程同時運行,並且它們試圖訪問相同的資源,就會遇到一個問題。舉個例子來講,兩個線程不能將信息同時發送給一臺打印機。爲解決這個問題,對那些可共享的資源來講(好比打印機),它們在使用期間必須進入鎖定狀態。因此一個線程可將資源鎖定,在完成了它的任務後,再解開(釋放)這個鎖,使其餘線程能夠接着使用一樣的資源。
多線程是爲了同步完成多項任務,不是爲了提升運行效率,而是爲了提升資源使用效率來提升系統的效率。線程是在同一時間須要完成多項任務的時候實現的。
一個採用了多線程技術的應用程序能夠更好地利用系統資源。其主要優點在於充分利用了CPU的空閒時間片,能夠用盡量少的時間來對用戶的要求作出響應,使得進程的總體運行效率獲得較大提升,同時加強了應用程序的靈活性。更爲重要的是,因爲同一進程的全部線程是共享同一內存,因此不須要特殊的數據傳送機制,不須要創建共享存儲區或共享文件,從而使得不一樣任務之間的協調操做與運行、數據的交互、資源的分配等問題更加易於解決。
● 請你說一下線程之間通訊的手段
參考回答:
使用全局變量
主要因爲多個線程可能更改全局變量,所以全局變量最好聲明爲volatile
使用消息實現通訊
在Windows程序設計中,每個線程均可以擁有本身的消息隊列(UI線程默認自帶消息隊列和消息循環,工做線程須要手動實現消息循環),所以能夠採用消息進行線程間通訊sendMessage,postMessage。
使用事件CEvent類實現線程間通訊
Event對象有兩種狀態:有信號和無信號,線程能夠監視處於有信號狀態的事件,以便在適當的時候執行對事件的操做。
● 請你說一下死鎖
參考回答:
一、死鎖是指在一組進程中的各個進程均佔有不會釋放的資源,但因互相申請被其餘進程所站用不會釋放的資源而處於的一種永久等待狀態。死鎖的四個必要條件:
互斥條件(Mutual exclusion):資源不能被共享,只能由一個進程使用。
請求與保持條件(Hold and wait):已經獲得資源的進程能夠再次申請新的資源。
非剝奪條件(No pre-emption):已經分配的資源不能從相應的進程中被強制地剝奪。
循環等待條件(Circular wait):系統中若干進程組成環路,該環路中每一個進程都在等待相鄰進程正佔用的資源。
java中產生死鎖可能性的最根本緣由是:1)是多個線程涉及到多個鎖,這些鎖存在着交叉,因此可能會致使了一個鎖依賴的閉環;2)默認的鎖申請操做是阻塞的。
如,線程在得到一個鎖L1的狀況下再去申請另一個鎖L2,也就是鎖L1想要包含了鎖L2,在得到了鎖L1,而且沒有釋放鎖L1的狀況下,又去申請得到鎖L2,這個是產生死鎖的最根本緣由。
二、避免死鎖:
• 方案一:破壞死鎖的循環等待條件。
• 方法二:破壞死鎖的請求與保持條件,使用lock的特性,爲獲取鎖操做設置超時時間。這樣不會死鎖(至少不會無盡的死鎖)
• 方法三:設置一個條件遍歷與一個鎖關聯。該方法只用一把鎖,沒有chopstick類,將競爭從對筷子的爭奪轉換成了對狀態的判斷。僅當左右鄰座都沒有進餐時才能夠進餐。提高了併發度。
● 請你回答一下進程同步的方法
參考回答:
一、臨界區(Critical Section):經過對多線程的串行化來訪問公共資源或一段代碼,速度快,適合控制數據訪問。
優勢:保證在某一時刻只有一個線程能訪問數據的簡便辦法
缺點:雖然臨界區同步速度很快,但卻只能用來同步本進程內的線程,而不可用來同步多個進程中的線程。
二、互斥量(Mutex):爲協調共同對一個共享資源的單獨訪問而設計的。
互斥量跟臨界區很類似,比臨界區複雜,互斥對象只有一個,只有擁有互斥對象的線程才具備訪問資源的權限。
優勢:使用互斥不只僅可以在同一應用程序不一樣線程中實現資源的安全共享,並且能夠在不一樣應用程序的線程之間實現對資源的安全共享。
缺點:①互斥量是能夠命名的,也就是說它能夠跨越進程使用,因此建立互斥量須要的資源更多,因此若是隻爲了在進程內部是用的話使用臨界區會帶來速度上的優點並可以減小資源佔用量。由於互斥量是跨進程的互斥量一旦被建立,就能夠經過名字打開它。
②經過互斥量能夠指定資源被獨佔的方式使用,但若是有下面一種狀況經過互斥量就沒法處理,好比如今一位用戶購買了一份三個併發訪問許可的數據庫系統,能夠根據用戶購買的訪問許可數量來決定有多少個線程/進程能同時進行數據庫操做,這時候若是利用互斥量就沒有辦法完成這個要求,信號量對象能夠說是一種資源計數器。
三、信號量(Semaphore):爲控制一個具備有限數量用戶資源而設計。它容許多個線程在同一時刻訪問同一資源,可是須要限制在同一時刻訪問此資源的最大線程數目。互斥量是信號量的一種特殊狀況,當信號量的最大資源數=1就是互斥量了。
優勢:適用於對Socket(套接字)程序中線程的同步。(例如,網絡上的HTTP服務器要對同一時間內訪問同一頁面的用戶數加以限制,只有不大於設定的最大用戶數目的線程可以進行訪問,而其餘的訪問企圖則被掛起,只有在有用戶退出對此頁面的訪問後纔有可能進入。)
缺點:①信號量機制必須有公共內存,不能用於分佈式操做系統,這是它最大的弱點;
②信號量機制功能強大,但使用時對信號量的操做分散, 並且難以控制,讀寫和維護都很困難,加劇了程序員的編碼負擔;
③核心操做P-V分散在各用戶程序的代碼中,不易控制和管理,一旦錯誤,後果嚴重,且不易發現和糾正。
四、事件(Event): 用來通知線程有一些事件已發生,從而啓動後繼任務的開始。
優勢:事件對象經過通知操做的方式來保持線程的同步,而且能夠實現不一樣進程中的線程同步操做。
● 請問進程線程的區別,進程間怎麼相互通訊,什麼是多線程,什麼是併發
參考回答:
進程和線程的區別有如下幾點
一、進程是資源分配的最小單位,線程是程序執行的最小單位
二、進程有本身獨立地址空間,每啓動一個進程,系統就會爲它分配地址空間,創建數據表來維護代碼段,堆棧段,數據段,而線程是共享進程中的數據的,使用相同的地址空間,可是CPU切換一個線程的花費遠比進程要小,
三、線程之間通訊方式更方便,同一進程下的線程共享全局變量等數據,而進程之間的通訊方式須要以通訊的方式進行,
四、多線程程序中只要有一個線程死掉了,整個進程也死掉了,而一個進程死掉了,並不會對另外一個進程形成影響,由於進程有本身獨立的地址空間
進程間的通訊方式:
一、無名管道通訊,數據只能單向流動,只能在具備親緣的進程間使用
二、高級管道通訊,將領一個程序看成一個新的進程在當前程序中啓動,則他算是當前進程的子進程
三、有名管道通訊,容許無親緣關係進程間的通訊
四、消息隊列通訊,消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識,消息隊列克服了信息傳遞信息少等缺點
五、信號量通訊,信號量用於控制多個進程對共享資源的訪問
六、信號通訊,用於通知接受進程某個事件已經發生
七、共享內存通訊,共享內存映射一段能被其餘進程所訪問的內存,每每與其餘通訊機制配合使用,來實現進程間的同步和通訊
八、套接字通訊,他用於不一樣機器之間的進程通訊
什麼是多線程
多線程就是指一個進程中同時有多個執行路徑正在執行
併發指在操做系統中,一個時間段中有幾個程序都已處於已啓動運行到運行完畢之間,且這幾個程序都是在同一個處理機上面,但任意時刻點上只有一個程序在處理機上運行。