阿里二面面經

2022-07-05 08:42:12 字數 4217 閱讀 7267

ibm測試,切換執行緒context的時候,windows比linux快一倍多。進出最快的鎖(windows2k的 critical section和linux的pthread_mutex),windows比linux的要快五倍左右。可見多執行緒這個具體的領域內,linux還是稍遜windows一點。這應該是情有可原的,畢竟unix家族都是從多程序過來的,而 windows從頭就是多執行緒的。

(1).   乙個程序中所有的執行緒共享全域性變臉和記憶體

(2).   程式邏輯和控制方便

(3).   執行緒方式消耗的總資源比程序要好

(1).   每個執行緒和主程式共用位址空間,受限於2g位址空間

(2).  乙個執行緒的崩潰可能影響到整個程式的穩定性;

(3).  到達一定的執行緒數程度後,即使再增加cpu也無法提高效能,例如windows server 2003,大約是1500個左右的執行緒數就快到極限了(執行緒堆疊設定為1m),如果設定執行緒堆疊為2m,還達不到1500個執行緒總數; 執行緒能夠提高的總效能有限,而且執行緒多了之後,執行緒本身的排程也是乙個麻煩事兒,需要消耗較多的cpu 

(1).   多個程序相互獨立,不影響程式的穩定性,子程序崩潰沒關係

(2).   通過增加cpu可以擴充效能

(4).   可以儘量減少執行緒加鎖/解鎖的影響,極大提高效能,就算是執行緒執行的模組演算法效率低也沒關係;

(1).  邏輯控制複雜,需要和主程式互動;

(2).  需要跨程序邊界,如果有大資料量傳送,就不太好,適合小資料量傳送、密集運算

(3).    多程序排程開銷比較大 

最好是多程序和多執行緒結合,即根據實際的需要,每個cpu開啟乙個子程序,這個子程序開啟多執行緒可以為若干同型別的資料進行處理。當然你也可以利用多執行緒+多cpu+輪詢方式來解決問題……方法和手段是多樣的,關鍵是自己看起來實現方便有能夠滿足要求,代價也合適

伺服器併發:大量客戶端同時訪問,響應多個客戶端。

對於人數少的,資料互動量小的,單程序,單工作執行緒即可處理。

io密集型程式:工作執行緒處理的**函式,處於io阻塞狀態,比如阻塞狀態的send recv,資料庫讀寫操做等,此時的io操做會阻塞執行緒,此時切換執行緒處理任務,可以提公升伺服器效率。io密集型程式由於大部分時間處於阻塞操做,cpu利用率很低,加多執行緒,可提公升cpu利用率,利用多執行緒遮蔽掉執行緒阻塞時間。

cpu密集型程式:cpu利用率較高,程式任務並沒有太多io操做,多執行緒對其並沒有多大提公升,相反,過多執行緒的切換,反而會浪費cpu時間,降低伺服器效率

程序切換分兩步

1.切換頁目錄以使用新的位址空間。

2.切換核心棧和硬體上下文。

對於linux來說,執行緒和程序的最大區別就在於位址空間。對於執行緒切換,第1步是不需要做的,第2是程序和執行緒切換都要做的。所以明顯是程序切換代價大。

執行緒安全:要確保函式執行緒安全,主要需要考慮的是執行緒之間的共享變數。屬於同一程序的不同執行緒會共享程序記憶體空間中的全域性區和堆,而私有的執行緒空間則主要包括棧和暫存器。因此,對於同一程序的不同執行緒來說,每個執行緒的區域性變數都是私有的,而全域性變數、區域性靜態變數、分配於堆的變數都是共享的。在對這些共享變數進行訪問時,如果要保證執行緒安全,則必須通過加鎖的方式。

可重入:概念基本沒有比較正式的完整解釋,但是它比執行緒安全要求更嚴格。根據經驗,所謂「重入」,常見的情況是,程式執行到某個函式foo()時,收到訊號,於是暫停目前正在執行的函式,轉到訊號處理函式,而這個訊號處理函式的執行過程中,又恰恰也會進入到剛剛執行的函式foo(),這樣便發生了所謂的重入。此時如果foo()能夠正確的執行,而且處理完成後,之前暫停的foo()也能夠正確執行,則說明它是可重入的

可重入與執行緒安全並不等同,一般說來,可重入的函式一定是執行緒安全的,但反過來不一定成立。

1思路一:每個程序/執行緒處理乙個連線

這一思路最為直接。但是由於申請程序/執行緒會占用相當可觀的系統資源,同時對於多程序/執行緒的管理會對系統造成壓力,因此這種方案不具備良好的可擴充套件性。

因此,這一思路在伺服器資源還沒有富裕到足夠程度的時候,是不可行的。即便資源足夠富裕,效率也不夠高。總之,此思路技術實現會使得資源占用過多,可擴充套件性差。

2思路二:每個程序/執行緒同時處理多個連線(io多路復用)

io多路復用從技術實現上又分很多種,我們逐一來看看下述各種實現方式的優劣。

實現方式1:傳統思路最簡單的方法是迴圈挨個處理各個連線,每個連線對應乙個 socket,當所有 socket 都有資料的時候,這種方法是可行的。但是當應用讀取某個 socket 的檔案資料不 ready 的時候,整個應用會阻塞在這裡等待該檔案控制代碼,即使別的檔案控制代碼 ready,也無法往下處理。

實現小結:直接迴圈處理多個連線。

問題歸納:任一檔案控制代碼的不成功會阻塞住整個應用。

實現方式2:select要解決上面阻塞的問題,思路很簡單,如果我在讀取檔案控制代碼之前,先查下它的狀態,ready 了就進行處理,不 ready 就不進行處理,這不就解決了這個問題了嘛?於是有了 select 方案。用乙個 fd_set 結構體來告訴核心同時監控多個檔案控制代碼,當其中有檔案控制代碼的狀態發生指定變化(例如某控制代碼由不可用變為可用)或超時,則呼叫返回。之後應用可以使用 fd_isset 來逐個檢視是哪個檔案控制代碼的狀態發生了變化。這樣做,小規模的連線問題不大,但當連線數很多(檔案控制代碼個數很多)的時候,逐個檢查狀態就很慢了。因此,select 往往存在管理的控制代碼上限(fd_setsize)。同時,在使用上,因為只有乙個字段記錄關注和發生事件,每次呼叫之前要重新初始化 fd_set 結構體。

intselect(intnfds, fd_set

*readfds, fd_set *writefds, fd_set *exceptfds, structtimeval

*timeout);

實現小結:有連線請求抵達了再檢查處理。

問題歸納:控制代碼上限+重複初始化+逐個排查所有檔案控制代碼狀態效率不高。

實現方式3:poll 主要解決 select 的前兩個問題:通過乙個 pollfd 陣列向核心傳遞需要關注的事件消除檔案控制代碼上限,同時使用不同字段分別標註關注事件和發生事件,來避免重複初始化。

實現小結:設計新的資料結構提供使用效率。

問題歸納:逐個排查所有檔案控制代碼狀態效率不高。

實現方式4:epoll既然逐個排查所有檔案控制代碼狀態效率不高,很自然的,如果呼叫返回的時候只給應用提供發生了狀態變化(很可能是資料 ready)的檔案控制代碼,進行排查的效率不就高多了麼。epoll 採用了這種設計,適用於大規模的應用場景。實驗表明,當檔案控制代碼數目超過 10 之後,epoll 效能將優於

select 和 poll;當檔案控制代碼數目達到 10k 的時候,epoll 已經超過 select 和

poll 兩個數量級。

實現小結:只返回狀態變化的檔案控制代碼。

問題歸納:依賴特定平台(linux)。

因為linux是網際網路企業中使用率最高的作業系統,epoll就成為c10k killer、高併發、高效能、非同步非阻塞這些技術的代名詞了。freebsd推出了kqueue,linux推出了epoll,windows推出了iocp,solaris推出了/dev/poll。這些作業系統提供的功能就是為了解決c10k問題。epoll技術的程式設計模型就是非同步非阻塞**,也可以叫做reactor,事件驅動,事件輪循(eventloop)。nginx,libevent,node.js這些就是epoll時代的產物。

實現方式5:由於epoll,

kqueue, iocp每個介面都有自己的特點,程式移植非常困難,於是需要對這些介面進行封裝,以讓它們易於使用和移植,其中libevent庫就是其中之一。跨平台,封裝底層平台的呼叫,提供統一的 api,但底層在不同平台上自動選擇合適的呼叫。按照libevent的官方**,libevent庫提供了以下功能:當乙個檔案描述符的特定事件(如可讀,可寫或出錯)發生了,或乙個定時事件發生了,libevent就會自動執行使用者指定的**函式,來處理事件。目前,libevent已支援以下介面/dev/poll, kqueue, event ports, select, poll 和 epoll。libevent的內部事件機制完全是基於所使用的介面的。因此libevent非常容易移植,也使它的擴充套件性非常容易。目前,libevent已在以下作業系統中編譯通過:linux,bsd,mac os x,solaris和windows。使用libevent庫進行開發非常簡單,也很容易在各種unix平台上移植。

阿里二面面經

很榮幸等來了阿里的二面,感覺自己發揮得很不好,但是我還是想記錄一下我的面試問題,希望自己好好反思反思自己的問題出在哪 1 聊學習 2 聊專案 3 第三正規化的特點和缺陷 4 如何抽象出資料庫的表 5 對juc的認識和理解 6 為什麼低版本的reentrantlock在高併發下比synchronize...

阿里c 一面面經

1 多型,虛函式與虛函式表 2 智慧型指標的作用及實現 3 sizeof,不能使用sizeof的情況下判斷系統的位數?4 三次握手,四次揮手,中間的等待 5 空class的大小,包含int和虛函式的大小 6 鍊錶是否有環,o 1 時間複雜度刪除指定節點,海量資料處理 topk 7 執行緒安全 單例模...

阿里一面 二面 交叉面 面經

面試完就叫我第二天去公司進行現場面試 交叉面 其實我一開始是不知道我現場面試算是第幾面 一開始叫我實現乙個lrucache,然後面試官去面了另外乙個貌似是社招的人。過了二十分鐘,面試官又帶著另外乙個面試官過來了 看來是換人面我了 我運氣不錯,碰到的面試官人都不錯。一開始做個自己介紹,然後面試官在看簡...