1. 程式人生 > >那些讓你起飛的計算機基礎知識

那些讓你起飛的計算機基礎知識

  1. 資訊的表示和處理

計算機如何表示整數:有符號數和無符號數,尤其是如何用補碼錶示負數,數字的取值範圍。

計算機如何表示浮點數,為什麼小數的二進位制表示法只能近似表示十進位制小數。

數值的轉換、移位

這幾點非常重要,因為幾乎所有的程式語言都有資料型別,而最基本資料型別必然包括整數和浮點數。

搞不清這些表示和運算,在程式設計中就會遇到一些稀奇古怪的問題。

  1. 從彙編層面理解程式的執行

順序、分支、迴圈、函式呼叫、陣列、結構體等在彙編層面是怎麼實現的,暫存器和記憶體是怎麼使用的。

理解了這些其實也就理解了馮諾依曼計算機體系結構,這是計算機學科一個基礎性的東西。

知道程式在底層是怎麼運轉的, 對於學習各種虛擬機器有很大的幫助,比如JVM,它要解析執行的是位元組碼,位元組碼本質上要表達的就是這些東西,只不過有所擴充套件。

理解了棧幀,就能理解函式呼叫的本質,遞迴,以及尾遞迴的實現。還有安全相關的概念,如緩衝區溢位這個臭名卓著的漏洞及其防範辦法。

  1. 程序和執行緒

程式設計師必備的知識,不瞭解這個,簡直是無法程式設計。

需要掌握程序的地址空間,程式碼在哪裡,堆在哪裡,棧在哪裡。

要準確理解程序和執行緒之間的關係,為什麼說程序是擁有資源的基本單位, 執行緒是CPU排程的基本單位?

程序切換和執行緒切換之間的區別和聯絡。

他們是如何建立,執行,有哪些狀態,狀態之間的轉換。 由此會涉及到併發和並行,執行緒之間的競爭和合作。

鎖的本質(硬體層面),樂觀鎖,悲觀鎖,死鎖等問題。

執行緒的實現方式,使用者級執行緒和核心級執行緒的對應方式。

在程式設計的過程中,有些知識點會直接使用,如多執行緒程式設計,鎖。 還有一些概念能用到很多地方,例如CAS,不僅僅是程式語言的概念,還能在更新資料庫時使用。再比如你理解了執行緒的實現方式,迅速就能掌握go語言中併發的手段:goroutine。

  1. 儲存器的層次結構

Tomcat用了多執行緒執行請求,Redis用了單執行緒來處理請求,Node.js也用了單執行緒來,這是為什麼? 祕密都在儲存器的層次結構。

人類製造的計算機裝置之間有著巨大的速度差異:

總之,CPU超級快,記憶體比較快,硬碟非常慢,網路更慢, 這個速度差異是IT行業的一個核心問題,人類想了很多辦法試圖去彌補這個差異:多執行緒,快取,非同步,多路複用,硬體層面的DMA。

記著下面這張圖,每當你遇到某個軟體的特性的時候,想一想和它有什麼關係:

在這裡插入圖片描述

  1. 資料結構和演算法

它的重要性我羅嗦過很多次了,不用再重複了, 我就舉個最簡單的例子: 理解了B+ Tree才能理解MySQL的InnoDB的索引,理解了索引才能更好地優化查詢,對吧?

  1. 計算機網路

現在的程式基本上都是網路程式, 所以這也是一個必備的基礎知識,學習計算機網路的一大好處就是和工作直接相關,能直接使用,比較有動力。

HTTP協議肯定跑不掉,TCP,UDP也得會,尤其是TCP可靠傳輸的原理:如何在一個不可靠的網路中進行可靠的傳輸, 這是無數前輩總結的經驗,一定得掌握。

要理解什麼是通訊協議,也許某一天你自己就需要定製一個協議來傳輸資料。

分組交換是什麼意思? 協議分層的本質是什麼? 什麼叫無狀態的協議?

Socket相關的程式設計更是重點,尤其是涉及到伺服器端高併發的時候,如何維持和處理這些海量的socket, epoll等技術就得上場了。

還有非常重要的HTTPs的基本原理,也是網路安全的精華所在:對稱加密,非對稱加密,訊息摘要,數字證書,中間人攻擊。

  1. 資料庫

不多說,關係模型、正規化、SQL、索引、事務等知識都得掌握,尤其是要了解他們的實現方式。

  1. 分散式的基礎知識

這些已經偏向應用層面了,但是現在很多系統都是分散式的了,分散式就變成了一種基礎知識。

系統通訊:RPC, 訊息佇列等

負載均衡的原理

CAP原理,BASE原理,冪等性,一致性模型(強一致性,最終一致性…)和相關協議(兩階段提交,Raft,Paxos…)

資料分片:取模演算法,一致性Hash,虛擬桶

  1. 基本的設計思想

下面這幾種設計思想對我影響很大,需要大家特別注意。但是掌握起來卻很不容易,需要在實踐中不斷地體會:

正交:各個概念之間可以獨立變化

抽象:拋棄細節,找到本質和共性

《深入理解計算機系統》一書中提到:“指令集是對CPU的抽象, 檔案是對輸入/輸出裝置的抽象, 虛擬儲存器是對程式儲存的抽象, 程序是對一個正在執行的程式的抽象, 而虛擬機器是對整個計算機(包括作業系統、處理器和程式)的抽象。 如果你對這句話透徹理解了,說明對計算機系統的認識已經很深刻了。

分層:我只想和我的鄰居打交道, 如網路協議,Web應用開發。

分而治之:大事化小,小事化了,架構設計必備。

  1. 關鍵點來了,怎麼學習呢?

我原來的方式是先看書,看了很多書,資料結構,作業系統,彙編,網路… 這種辦法的最大問題就是枯燥(嗯,那時候還沒有碼農翻身這樣用故事講解技術的文章)。

理論多,實踐少,很多知識點體會不深, 等到參與的專案多了,Coding多了,這些知識點才慢慢地鮮活起來。

一種更加有效的辦法是從工作中用到的知識點出發,從這個知識點向外擴充套件,由點到線,由線到面,然後讓各個層次都連線起來,形成一個立體的網路。

切記,學習是一個螺旋上升的過程,想要上升就得深度思考,多問幾個為什麼。

比如工作中用到了Redis,你在學習過程中發現這個Redis用了單執行緒來處理讀寫請求,為什麼要這麼做? 對於成千上萬的請求它是如何處理的? 然後再聯想一下別的軟體:Tomcat為什麼不這麼幹? 想回答這些問題,需要發掘很多基礎知識。

這樣做的次數多了,積累到一定程度,量變就會引起質變,整個系統就被你看透了,你的知識又擴大了一圈,更多的疑問出現了…

  • 轉載自微信公眾號:碼農翻身
    在這裡插入圖片描述