Go語(yǔ)言學(xué)習(xí)教程(十六)

一、死鎖

* 在主goroutine中向無(wú)緩存channel添加內(nèi)容或在主goroutine中向channel添加內(nèi)容且添加內(nèi)容的個(gè)數(shù)已經(jīng)大于channel緩存?zhèn)€數(shù)就會(huì)產(chǎn)生死鎖

?? ?fatal error : all goroutines are asleep -deadlock!

* 死鎖:在程序中多個(gè)進(jìn)程(Golang中g(shù)oroutine)由于相互競(jìng)爭(zhēng)資源而產(chǎn)生的阻塞(等待)狀態(tài),而這種狀態(tài)一直保持下去,此時(shí)稱這個(gè)線程是死鎖狀態(tài)

* 在Golang中使用無(wú)緩存channel時(shí)一定要注意.以下是一個(gè)最簡(jiǎn)單的死鎖程序

????* 主協(xié)程中有ch<-1,無(wú)緩存channel無(wú)論添加還是取出數(shù)據(jù)都會(huì)阻塞goroutine,當(dāng)前程序無(wú)其他代碼,主goroutine會(huì)一直被阻塞下去,此時(shí)主goroutine就是死鎖狀態(tài)

?? ?func main() {

???? ??ch := make(chan int)

???? ??ch <- 1

?? ?}

* 而下面代碼就不會(huì)產(chǎn)生死鎖

????* 通過(guò)代碼示例可以看出,在使用無(wú)緩存channel時(shí),特別要注意的是在主協(xié)程中要操作channel代碼

?? ?func main() {

????? ?ch := make(chan int)

????? ?go func() {

???????? ?ch <- 1

???????? ?fmt.Println("執(zhí)行g(shù)oroutine")

????? ?}()

????? ?time.Sleep(5e9)

????? ?fmt.Println("程序執(zhí)行結(jié)束")

?? ?}

二、有緩存通道

* 創(chuàng)建一個(gè)有緩存通道

func main() {

???ch := make(chan int, 3) //緩存大小3,里面消息個(gè)數(shù)小于等于3時(shí)都不會(huì)阻塞goroutine

???ch <- 1

???ch <- 2

???ch <- 3

???ch <- 4 //此行出現(xiàn)死鎖,超過(guò)緩存大小數(shù)量

}

* 在Golang中有緩存channel的緩存大小是不能改變的,但是只要不超過(guò)緩存數(shù)量大小,都不會(huì)出現(xiàn)阻塞狀態(tài)

?? ?func main() {

????? ?ch := make(chan int, 3) //緩存大小3,里面消息個(gè)數(shù)小于等于3時(shí)都不會(huì)阻塞goroutine

????? ?ch <- 1

????? ?fmt.Println(<-ch)

???? ??ch <- 2

????? ?fmt.Println(<-ch)

????? ?ch <- 3

????? ?ch <- 4

???? ??fmt.Println(len(ch))//輸出2,表示channel中有兩個(gè)消息

???? ??fmt.Println(cap(ch))//輸出3,表示緩存大小總量為3

?? ?}

三、select簡(jiǎn)介

* Golang中select和switch結(jié)構(gòu)特別像,但是select中case的條件只能是I/O

* select 的語(yǔ)法(condition是條件)

?? ?select{

??? ??case condition:

??? ??case condition:

??? ??default:

?? ?}

* select執(zhí)行過(guò)程:

????* 每個(gè)case必須是一個(gè)IO操作

????* 哪個(gè)case可以執(zhí)行就執(zhí)行哪個(gè)

????* 多個(gè)case都可以執(zhí)行,隨機(jī)執(zhí)行一個(gè)

????* 所有case都不能執(zhí)行時(shí),執(zhí)行default

????* 所有case都不能執(zhí)行,且沒(méi)有default,將會(huì)阻塞

func main() {

???runtime.GOMAXPROCS(1)

???ch1 := make(chan int, 1)

???ch2 := make(chan string, 1)

???ch1 <- 1

???ch2 <- "hello"

???select {

???case value := <-ch1:

??????fmt.Println(value)

???case value := <-ch2:

??????fmt.Println(value)

???}

}

* select多和for循環(huán)結(jié)合使用,下面演示出了一直在接收消息的例子

func main() {

????ch := make(chan int)

????for i := 1; i <= 5; i++ {

????????go func(arg int) {

????????????ch <- arg

????????}(i)

????}

??//如果是一直接受消息,應(yīng)該是死循環(huán)for{},下面代碼中是明確知道消息個(gè)數(shù)

????for i := 1; i <= 5; i++ {

????????select {

????????case c := <-ch:

????????????fmt.Println("取出數(shù)據(jù)", c)

????????default:

????????????//沒(méi)有default會(huì)出現(xiàn)死鎖

????????}

????}

????fmt.Println("程序執(zhí)行結(jié)束")

}

* break可以對(duì)select生效,如果for中嵌套select,break選擇最近結(jié)構(gòu)

四、GC

* GC英文全稱 garbage collector

* Go語(yǔ)言GC是相對(duì)C/C++語(yǔ)言非常重要的改進(jìn)

* 一些常用GC算法

????* 引用計(jì)算法:當(dāng)對(duì)象被引用時(shí)計(jì)算器加一.不被引用計(jì)數(shù)器減一

????????* PHP和Object-C使用

????????* 相互引用無(wú)法回收

????????* 計(jì)數(shù)增加消耗

????* Mark And Sweep 標(biāo)記和清除算法:停止程序運(yùn)行,遞歸遍歷對(duì)象,進(jìn)行標(biāo)記。標(biāo)記完成后將所有沒(méi)有引用的對(duì)象進(jìn)行清除

????????* 由于標(biāo)記需要停止程序(Stop the world),當(dāng)對(duì)象特別多時(shí),標(biāo)記和清除過(guò)程比較耗時(shí)(可能幾百毫秒),很難接受

????* 三色標(biāo)記法:是Mark And Sweep的改進(jìn)版.從邏輯上分為白色區(qū)(未搜索),灰色區(qū)(正搜索),黑色區(qū)(已搜索).灰色區(qū)內(nèi)容是子引用沒(méi)有進(jìn)行搜索,黑色區(qū)表示子引用存在

????* 分代收集:一般情況都有三代,例如java中新生代,老年代,永久代.當(dāng)新生代中帶有閾值時(shí)會(huì)把對(duì)象放入到老年代,相同道理老年代內(nèi)容達(dá)到閾值會(huì)放入到永久代

五、Go語(yǔ)言中的GC

* Go語(yǔ)言中采用Stop The World方式

* Golang每個(gè)版本基本上都會(huì)對(duì)GC進(jìn)行優(yōu)化,從Golang1.5開始支持并發(fā)(concurrent )收集,從1.8版本已經(jīng)把STW時(shí)間優(yōu)化到了100微妙,通常只需要10微秒以下.且在1.10版本時(shí)再次優(yōu)化減少GC對(duì)CPU占用

* Go語(yǔ)言中GC是自動(dòng)運(yùn)行的,在下列情況下會(huì)觸發(fā)GC

????* 當(dāng)需要申請(qǐng)內(nèi)存時(shí),發(fā)現(xiàn)GC是上次GC兩倍時(shí)會(huì)觸發(fā)

????* 每2分鐘自動(dòng)運(yùn)行一次GC

* GC調(diào)優(yōu)

????* 小對(duì)象復(fù)用,局部變量盡量少聲明,多個(gè)小對(duì)象可以放入到結(jié)構(gòu)體,方便GC掃描

????* 少用string的”+”

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容