1、線程、鎖html
一、Posix Thread互斥鎖node
線程鎖建立c++
a.靜態建立面試
pthread_mutex_tmutex = PTHREAD_MUTEX_INITIALIZER;算法
b.動態建立數據庫
pthread_mutex_tmutex = pthread_mutex_init(pthread_mutex_t*mutex,constpthread_mutexattr_t*mutexattr);數組
互斥鎖的屬性安全
互斥鎖的屬性在建立鎖的時候指定,在LinuxThreads實現中僅有一個鎖類型屬性,不一樣的鎖類型在試圖對一個已經被鎖定的互斥鎖加鎖時表現不一樣。服務器
a.PTHREAD_MUTEX_TIMED_NP這是缺省值,也就是普通鎖。當一個線程加鎖之後,其他請求鎖的線程將造成一個等待隊列,並在解鎖後按優先級得到鎖。這種鎖策略保證了資源分配的公平性。網絡
b.PTHREAD_MUTEX_RECURSIVE_NP嵌套鎖,容許同一個線程對同一個鎖成功得到屢次,並經過屢次unlock解鎖。若是是不一樣線程請求,則在加鎖線程解鎖時從新競爭。 c. PTHREAD_MUTEX_ERRORCHECK_NP檢錯鎖,若是同一個線程請求同一個鎖,則返回EDEADLK,不然與PTHREAD_MUTEX_TIMED_NP類型動做相同。這樣就保證當不容許屢次加鎖時不會出現最簡單狀況下的死鎖。
d.PTHREAD_MUTEX_ADAPTIVE_NP適應鎖,動做最簡單的鎖類型,僅等待解鎖後從新競爭。
鎖操做
int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)
pthread_mutex_trylock() 與pthread_mutex_lock()相似,不一樣的是在鎖已經被佔據時返回EBUSY而不是掛起等待
Linux線程
Linux系統下的多線程遵循POSIX線程接口,稱爲pthread。編寫Linux下的多線程程序,須要使用頭文件pthread.h
線程建立
int pthread_create((pthread_t *thread,constpthread_attr_t *__attr, void *(*__start_routine)(void *), void *__arg))
第一個參數爲指向線程標識符的指針,第二個參數用來設置線程屬性,第三個參數是線程運行函數的起始地址,最後一個參數是運行函數的參數。返回0表示建立成功,不然不成功。
pthread_tid;pthread_create(&id,NULL,(void*) thread,NULL);
線程等待
int pthread_join __P ((pthread_t __th, void **__thread_return))
第一個參數爲被等待的線程標識符,第二個參數爲一個用戶定義的指針,它能夠用來存儲被等待線程的返回值。這個函數是一個線程阻塞的函數,調用它的函數將一直等待到被等待的線程結束爲止,當函數返回時,被等待線程的資源被收回。
線程終止
一個線程的結束有兩種途徑,一種是象咱們上面的例子同樣,函數結束了,調用它的線程也就結束了;另外一種方式是經過函數pthread_exit來實現。
void pthread_exit ((void *__retval)) __attribute__ ((__noreturn__))
惟一的參數是函數的返回代碼。
二、死鎖及其預防和處理方法
死鎖的規範定義以下:若是一個進程在等待只能由該進程中止才能引起的事件,那麼該進程就是死鎖的。
(1)產生死鎖的緣由
由於系統資源不足。
進程運行推動的順序不合適。
資源分配不當等。
(2)產生死鎖的四個必要條件
互斥條件:每一個資源要麼已經分配給了一個進程,要麼就是可用的。
佔有和等待條件:已經獲得了某個資源的進程能夠再請求新的資源。
不可搶佔條件:已經分配給一個進程的資源不能強制性地被搶佔,只能被佔有它的進程顯式地釋放;
環路等待條件:死鎖發生時,系統中必定有兩個或者兩個以上的進程組成的一條環路,該環路中的每一個進程都在等待着下一個進程所佔有的資源。
這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不知足,就不會發生死鎖。
(3)處理死鎖的四種策略:
鴕鳥策略(忽略死鎖);
檢測死鎖並恢復;
仔細對資源進行分配,動態地避免死鎖;
經過破壞引發死鎖的四個必要條件之一,防止死鎖的產生。
(4)死鎖避免
死鎖避免的主要算法是基於一個安全狀態 的概念。在任什麼時候刻,若是沒有死鎖發生,而且即便全部進程突然請求對資源的最大請求,也仍然存在某種調度次序可以使得每個進程運行完畢,則稱該狀態是安全的。從安全狀態出發,系統可以保證全部進程都能完成,而從不安全狀態出發,就沒有這樣的保證。
銀行家算法 :判斷對請求的知足是否會進入不安全狀態,若是是,就拒絕請求,若是知足請求後系統仍然是安全的,就予以分配。不安全狀態不必定引發死鎖,由於客戶不必定須要其最大貸款額度。
2、C++
1. 虛函數的實現原理
虛函數表的建立和繼承
a. 基類的虛函數表的建立:首先在基類聲明中找到全部的虛函數,按照其聲明順序,編碼0,1,2,3,4……,而後按照此聲明順序爲基類建立一個虛函數表,其內容就是指向這些虛函數的函數指針,按照虛函數聲明的順序將這些虛函數的地址填入虛函數表中。例如若show放在虛函數聲明的第二位,則在虛函數表中也放在第二位。 b. 對於子類的虛函數表:首先將基類的虛函數表複製到該子類的虛函數表中。若子類重寫了基類的虛函數show,則將子類的虛函數表中存放show的函數地址(未重寫前存放的是子類的show虛函數的函數地址)更新爲重寫後函數的函數指針。若子類增長了一些虛函數的聲明,則將這些虛函數的地址加到該類虛函數表的後面。
經過虛函數表訪問對象的方法
當執行Base->show()時,要觀察show在Base基類中聲明的是虛函數仍是非虛函數。若爲虛函數將使用動態聯編(使用虛函數表決定如何調用函數),若爲非虛函數則使用靜態聯編(根據調用指針Base的類型來肯定調用哪一個類的成員函數)。此處假設show爲虛函數,首先:因爲檢查到Base指針類型所指的類Base中show定義爲虛函數,所以找到Base所指的對象,訪問對象獲得該對象所屬類的虛函數表地址。其次:查找show在Base類中聲明的位置在Base類中全部虛函數聲明中的位序。而後到Base所指對象的所屬類的虛函數表中訪問該位序的函數指針,從而獲得要執行的函數。
爲何要把析構函數定義爲虛函數?
new出來的是子類son的對象,採用一個父類father的指針來接收,故在析構的時候,編譯器由於只知道這個指針是父類的,因此只將父類部分的內存析構了,而不會去析構子類的內存,就形成了內存泄露。基類析構函數定義爲虛擬函數的時候,在子類的對象的首地址開始會有一塊基類的虛函數表拷貝,在析構子類對象的時候會刪除此虛函數表,此時會調用基類的析構函數,因此此時內存是安全的。
爲何虛函數比普通函數慢?
由於虛函數要經過查找虛函數表的方法訪問。
爲何構造函數不能是虛函數?
構造函數不能夠是虛函數的,這個很顯然,畢竟虛函數都對應一個虛函數表,虛函數表是存在對象內存空間的,若是構造函數是虛的,就須要一個虛函數表來調用,可是類還沒實例化沒有內存空間就沒有虛函數表,這根本就是個死循環。
內聯函數、構造函數和靜態成員函數能夠定義爲虛函數麼?爲何?
基類指針指向派生類時如何知道指向的是哪個派生類?
2. 正確區分重載、重寫和隱藏。
注意三個概念的適用範圍:處在同一個類中的函數纔會出現重載。處在父類和子類中的函數纔會出現重寫和隱藏。重載:同一類中,函數名相同,但參數列表不一樣。重寫:父子類中,函數名相同,參數列表相同,且有virtual修飾。隱藏:父子類中,函數名相同,參數列表相同,但沒有virtual修飾;函數名相同,參數列表不一樣,不管有無virtual修飾都是隱藏
基類中: (1)virtualvoidshow();//是虛函數(2)voidshow(int);//不是虛函數
子類中:(3)voidshow();//是虛函數(4)voidshow(int);//不是虛函數
1,2構成重載,3,4構成重載,1,3構成重寫,2,4構成隱藏。另外2,3也會構成隱藏,子類對象沒法訪問基類的void show(int)成員方法,可是因爲子類中4的存在致使了子類對象也能夠直接調用void show(int)函數,不過此時調用的函數不在是基類中定義的void show(int)函數2,而是子類中的與3重載的4號函數。
三、C對象和C++對象的區別(struct和class)
C++中的struct對C中的struct進行了擴充,它已經再也不只是一個包含不一樣數據類型的數據結構了,它已經獲取了太多的功能。struct能包含成員函數嗎? 能!struct能繼承嗎? 能!!struct能實現多態嗎? 能!!!
a. 默認的繼承訪問權限。struct是public的,class是private的。
b. struct做爲數據結構的實現體,它默認的數據訪問控制是public的,而class做爲對象的實現體,它默認的成員變量訪問控制是private的。
3、網絡
一、TCP和UDP
tcp是一種面向鏈接的、可靠的、基於字節流的傳輸層通訊協議。udp(用戶數據報協議)傳輸層協議,提供面向操做的簡單不可靠的非鏈接傳輸層服務,面向報文。
區別 a. tcp是基於鏈接的,可靠性高;udp是基於無鏈接的,可靠性較低; b. 因爲tcp是鏈接的通訊,須要有三次握手、從新確認等鏈接過程,會有延時,實時性差;同時過程複雜,也使其易於被攻擊;而udp無鏈接,無創建鏈接的過程,於是實時性較強,也稍安全; c. 在傳輸相同大小的數據時,tcp首部開銷20字節;udp首部開銷只有8個字節,tcp報頭比udp複雜,故實際包含的用戶數據較少。tcp無丟包,而udp有丟包,故tcp開銷大,udp開銷較小;
d .每條tcp鏈接只能是點到點的;udp支持一對1、一對多、多對1、多對多的交互通訊。
TCP的三次握手
第一次握手:客戶端發送一個tcp的syn標誌位置爲1的包(鏈接請求),指明客戶打算鏈接服務器的端口;SYN=1,seq=client_isn
第二次握手:當服務器收到鏈接請求以後,返回確認包(ack)應答,即將syn和ack標誌位同時致爲1(授予鏈接),併爲此次鏈接分配資源;SYN=1,ACK=1,seq = server_isn
第三次握手:客戶端收到服務器的授予鏈接請求以後,再次發送確認包(ack)(syn標誌位爲0,ack標誌位爲1),並分配資源,這樣tcp就創建鏈接了SYN=0,ACK=1,seq=client_isn+1
TCP和UDP的數據結構
a.TCP
structTCP_HEADER{shortm_sSourPort;// 源端口號16bitshortm_sDestPort;// 目的端口號16bitunsignedintm_uiSequNum;// 序列號32bitunsignedintm_uiAcknowledgeNum;// 確認號32bitshortm_sHeaderLenAndFlag;// 前4位:TCP頭長度;中6位:保留;後6位:標誌位shortm_sWindowSize;// 窗口大小16bitshortm_sCheckSum;// 檢驗和16bitshortm_surgentPointer;// 緊急數據偏移量16bit}
b.UDP
structUDP_HEADER{shortm_sSourPort;// 源端口號16bitshortm_sDestPort;// 目的端口號16bitshortm_size;//長度16bitshortm_sCheckSum;// 檢驗和16bit}
4、組合數學
5、數據庫
一、範式
常見的範式:第一範式(1NF),第二範式(2NF),第三範式(3NF)。下面就簡單介紹下這三個範式。
| name | tel | age |
| :--: | :-----: | :--: |
| 大寶 | 136 | 22 |
| 小明 | 132,158 | 21 |
第一範式(1NF):強調的是列的原子性,即列(屬性)不可以再分紅其餘幾列。
考慮這樣一個表:【聯繫人】(姓名,性別,電話)
若是在實際場景中,一個聯繫人有家庭電話和公司電話,那麼這種表結構設計就沒有達到 1NF。要符合 1NF 咱們只需把列(電話)拆分,即:【聯繫人】(姓名,性別,家庭電話,公司電話)。1NF 很好辨別,可是 2NF 和 3NF 就容易搞混淆。
第二範式(2NF):首先是 1NF,另外包含兩部份內容,一是表必須有一個主鍵;二是不能只依賴於主鍵的一部分。
學生課程 老師 老師職稱 教材 教室 上課時間
小明一年級語文(上) 大寶 副教授 《小學語文1》 101 14:30
一個學生上一門課,必定在特定某個教室。因此有(學生,課程)->教室
一個學生上一門課,必定是特定某個老師教。因此有(學生,課程)->老師
一個學生上一門課,他老師的職稱能夠肯定。因此有(學生,課程)->老師職稱
一個學生上一門課,必定是特定某個教材。因此有(學生,課程)->教材
一個學生上一門課,必定在特定時間。因此有(學生,課程)->上課時間
所以(學生,課程)是一個碼。
◆ 第三範式(3NF):首先是 2NF,另外非主鍵列必須直接依賴於主鍵,不能存在傳遞依賴。即不能存在:非主鍵列 A 依賴於非主鍵列 B,非主鍵列 B 依賴於主鍵的狀況。
6、數據結構
一、鏈表
(1)鏈表創建、插入、刪除
創建
Node *L;L =newNode; L =NULL;//不帶頭節點的初始化L->=NUll;//帶頭結點的初始化
頭尾插入元素
p->next = L; L = p;//頭插法
Node *tail =newNode;//尾插法Node *cur = L;while(cur->next!=NULL){ cur = cur->next;}tail = cur;tail->next = p;p->next =NULL;
精確插入
boolListInsert(List *L,intpos,Node *node){inti=1;Node *cur=newNode;cur = L;while(cur->next != Null && i != pose){ cur = cur->next; i++; }if(cur->next =NULL)returnfalse;else{ node->next = cur->next; cur ->next = node;returntrue; }}
精確刪除
boolListDelete(List *L,intpos){inti=1;Node *cur=newNode;cur = L;while(cur->next != Null && i != pose){ cur = cur->next; i++; }if(cur->next =NULL||i>pos)returnfalse;else{ cur->next = cur->next->nextdeletecur->nextreturntrue; }}
(2)鏈表反轉,環、
反轉
boolListReverse(List *L){ Node cur = L->next; Node *temp =newNode;while(cur->next!=NULL){ temp = cur; L->next->next = L; L->next = temp->next; cur = L->next; }returntrue;}
環
算法的思想是設定兩個指針p, q,其中p每次向前移動一步,q每次向前移動兩步。那麼若是單鏈表存在環,則p和q相遇;不然q將首先遇到NULL。
如何定義一個只能在棧上或者堆上生成對象的類?
sizeof(類),如何計算類的大小?
sizeof(結構體),如何計算結構體的大小?
結構體和類有什麼區別?
extern「C」有什麼做用?原理是什麼?
const修飾的變量和#define有什麼區別?
static有什麼做用?如何改變變量的生命週期和做用域?
volitale什麼做用?
new 和malloc有什麼不同?
指針和引用的區別?
STL容器有哪些?
vector內部數據結構是什?List/Map/Queue
STL,vector和List有什麼不同?map是用什麼數據結構實現的?
switch和if分支有什麼區別?
全局變量好用麼?
面向對象有哪些特色?如何體現?
面向對象的設計原則有哪些?
如何檢查內存泄漏?
從源代碼到可執行二進制文件,要通過哪些過程?
二維數組爲題
http://c.biancheng.net/cpp/html/79.html
//這是一個關於二維數組指針的問題。//假設定義一個int型的二維數組指針。intSec[2][3]={4,6,3,7,2,7};int**P = Sec; **p 等價 Sec[0][0] *p 等價 Sec[0] *(p+n) 等價 Sec[n] *(*(p+n)+m) 等價 Sec[n][m]//因此++m,爲行數增長爲afternoon一行,而*m輸出整行。
C++中不能重載的運算符:「?:」、「.」、「::」、「sizeof」和」.*」
各個容器的內部實現數據結構
數組越界
死循環
棧溢出
內存泄露
首先所謂的接口是指只包含純虛函數的抽象類,和普通的抽象類含不同
文末也分享給你們也是Linuxc++開發的學習資料
主要有C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK技術,面試技巧方面的資料技術討論。
感興趣的朋友戳這裏:等待領取