## 一、Golang Slice的擴容機制,有什么注意點?
#### 1、Go 中切片擴容策略:
* 首先判斷,如果新申請容量大于2倍的舊容量,最終容量就是新申請的容量
* 否則判斷,如果舊切片的長度小于1024,則最終容量就是舊容量的兩倍
* 否則判斷,如果舊切片長度大于等于1024,則最終容量從舊容量開始循環增加原來的 1/4, 直到最終容量大于等于新申請的容量
* 如果最終容量計算值溢出,則最終容量就是新申請容量
#### 2、擴容前后的Slice是否相同?
* 情況一:
原數組還有容量可以擴容(實際容量沒有填充完),這種情況下,擴容以后的數組還是指向原來的數組,對一個切片的操作可能影響多個指針指向相同地址的Slice。
* 情況二:
原來數組的容量已經達到了最大值,再想擴容, Go 默認會先開一片內存區域,把原來的值拷貝過來,然后再執行 append() 操作。這種情況絲毫不影響原數組。
要復制一個Slice,最好使用Copy函數。
## 二、互斥鎖,讀寫鎖,死鎖問題是怎么解決
* 互斥鎖
互斥鎖就是互斥變量mutex,用來鎖住臨界區的.
條件鎖就是條件變量,當進程的某些資源要求不滿足時就進入休眠,也就是鎖住了。當資源被分配到了,條件鎖打開,進程繼續運行;讀寫鎖,也類似,用于緩沖區等臨界資源能互斥訪問的。
* 讀寫鎖
通常有些公共數據修改的機會很少,但其讀的機會很多。并且在讀的過程中會伴隨著查找,給這種代碼加鎖會降低我們的程序效率。讀寫鎖可以解決這個問題。
[](https://github.com/KeKe-Li/golang-interview-questions/blob/master/src/images/61.jpg)
注意:寫獨占,讀共享,寫鎖優先級高
* 死鎖
一般情況下,如果同一個線程先后兩次調用lock,在第二次調用時,由于鎖已經被占用,該線程會掛起等待別的線程釋放鎖,然而鎖正是被自己占用著的,該線程又被掛起而沒有機會釋放鎖,因此就永遠處于掛起等待狀態了,這叫做死鎖(Deadlock)。 另外一種情況是:若線程A獲得了鎖1,線程B獲得了鎖2,這時線程A調用lock試圖獲得鎖2,結果是需要掛起等待線程B釋放鎖2,而這時線程B也調用lock試圖獲得鎖1,結果是需要掛起等待線程A釋放鎖1,于是線程A和B都永遠處于掛起狀態了。
死鎖產生的四個必要條件:
1. 互斥條件:一個資源每次只能被一個進程使用
2. 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
3. 不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
4. 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。 這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。
a. 預防死鎖
可以把資源一次性分配:(破壞請求和保持條件)
然后剝奪資源:即當某進程新的資源未滿足時,釋放已占有的資源(破壞不可剝奪條件)
資源有序分配法:系統給每類資源賦予一個編號,每一個進程按編號遞增的順序請求資源,釋放則相反(破壞環路等待條件)
b. 避免死鎖
預防死鎖的幾種策略,會嚴重地損害系統性能。因此在避免死鎖時,要施加較弱的限制,從而獲得 較滿意的系統性能。由于在避免死鎖的策略中,允許進程動態地申請資源。因而,系統在進行資源分配之前預先計算資源分配的安全性。若此次分配不會導致系統進入不安全狀態,則將資源分配給進程;否則,進程等待。其中最具有代表性的避免死鎖算法是銀行家算法。
c. 檢測死鎖
首先為每個進程和每個資源指定一個唯一的號碼,然后建立資源分配表和進程等待表.
d. 解除死鎖
當發現有進程死鎖后,便應立即把它從死鎖狀態中解脫出來,常采用的方法有.
e. 剝奪資源
從其它進程剝奪足夠數量的資源給死鎖進程,以解除死鎖狀態.
f. 撤消進程
可以直接撤消死鎖進程或撤消代價最小的進程,直至有足夠的資源可用,死鎖狀態.消除為止.所謂代價是指優先級、運行代價、進程的重要性和價值等。
## 三、什么是channel,為什么它可以做到線程安全?
Channel是Go中的一個核心類型,可以把它看成一個管道,通過它并發核心單元就可以發送或者接收數據進行通訊(communication),Channel也可以理解是一個先進先出的隊列,通過管道進行通信。
Golang的Channel,發送一個數據到Channel 和 從Channel接收一個數據 都是 原子性的。而且Go的設計思想就是:不要通過共享內存來通信,而是通過通信來共享內存,前者就是傳統的加鎖,后者就是Channel。也就是說,設計Channel的主要目的就是在多任務間傳遞數據的,這當然是安全的。
## 四、垃圾處理
[https://github.com/KeKe-Li/For-learning-Go-Tutorial/blob/master/src/spec/02.0.md](https://github.com/KeKe-Li/For-learning-Go-Tutorial/blob/master/src/spec/02.0.md)
## 五、并發編程概念是什么?
并行是指兩個或者多個事件在同一時刻發生;并發是指兩個或多個事件在同一時間間隔發生。
并行是在不同實體上的多個事件,并發是在同一實體上的多個事件。在一臺處理器上“同時”處理多個任務,在多臺處理器上同時處理多個任務。如hadoop分布式集群
并發偏重于多個任務交替執行,而多個任務之間有可能還是串行的。而并行是真正意義上的“同時執行”。
并發編程是指在一臺處理器上“同時”處理多個任務。并發是在同一實體上的多個事件。多個事件在同一時間間隔發生。并發編程的目標是充分的利用處理器的每一個核,以達到最高的處理性能。
- 一、經典(一)
- 二、經典(二)
- 三、經典(三)
- 四、經典(四)
- 五、經典(五)
- 六、經典(六)
- 七、經典(七)
- 八、經典(八)
- 九、經典(九)
- 十、經典(十)
- 十一、經典(十一)
- 十二、經典(十二)
- 其他
- 1、知識點一
- 2、面試集
- 3、負載均衡原理
- 4、LVS相關了解
- 5、微服務架構
- 6、分布式鎖實現原理
- 7、Etcd怎么實現分布式鎖
- 8、Redis的數據結構有哪些,以及實現場景
- 9、Mysql高可用方案有哪些
- 10、Go語言的棧空間管理是怎么樣的
- 11、Goroutine和Channel的作用分別是什么
- 12、Go中的鎖有哪些?三種鎖,讀寫鎖,互斥鎖,還有map的安全的鎖?
- 13、怎么限制Goroutine的數量
- 14、Goroutine和線程的區別?
- 15、中間件原理