《Go語(yǔ)言從入門到精通》Go語(yǔ)言的并發(fā)處理_第1頁(yè)
《Go語(yǔ)言從入門到精通》Go語(yǔ)言的并發(fā)處理_第2頁(yè)
《Go語(yǔ)言從入門到精通》Go語(yǔ)言的并發(fā)處理_第3頁(yè)
《Go語(yǔ)言從入門到精通》Go語(yǔ)言的并發(fā)處理_第4頁(yè)
《Go語(yǔ)言從入門到精通》Go語(yǔ)言的并發(fā)處理_第5頁(yè)
已閱讀5頁(yè),還剩24頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

Go語(yǔ)言的并發(fā)處理Go語(yǔ)言從入門到精通了解并發(fā)處理的基本概念與知識(shí)掌握Go語(yǔ)言中多任務(wù)的協(xié)同工作方式01CONCURENT02CONFLICT03TASKStarget目標(biāo)掌握Go語(yǔ)言中避免并發(fā)共享沖突的主要方法目錄導(dǎo)航11.1Go語(yǔ)言并發(fā)編程基礎(chǔ)ContentsGo語(yǔ)言并發(fā)處理的優(yōu)勢(shì)

先天優(yōu)勢(shì):是Go語(yǔ)言最重點(diǎn)解決的目標(biāo)之一

極其簡(jiǎn)單便捷:一條語(yǔ)句啟動(dòng)線程

輕量級(jí):輕松運(yùn)行上千線程

語(yǔ)言級(jí)的并發(fā)支持:go關(guān)鍵字與通道(chan)數(shù)據(jù)類型硬件級(jí)支持:先天支持多核CPU上的調(diào)度簡(jiǎn)單的Goroutine啟動(dòng)方式func

function1()

{

a

:=

1

for

{

a++

fmt.Println(a)

}}

go

function1()

go關(guān)鍵字一條語(yǔ)句啟動(dòng)一個(gè)線程*

goroutine雖然與線程有所不同,但廣義上我們還是可以稱之為線程主線程func

main()

{

go

function1()

for

{ time.Sleep(100

*

time.Millisecond)

}

}main函數(shù)運(yùn)行在主線程中主函數(shù)退出時(shí),所有g(shù)oroutine也將退出避免主線程占用過(guò)多CPU時(shí)間多核CPU并發(fā)分擔(dān)cpuCores

:=

runtime.NumCPU()

//

獲取實(shí)際CPU核數(shù)

runtime.GOMAXPROCS(2)

//

將可用CPU核數(shù)設(shè)為2目錄導(dǎo)航11.2并發(fā)處理時(shí)的共享沖突Contents共享沖突var

valueG

int

=

0var

stop1

bool

=

falsevar

stop2

bool

=

false

func

routine1(countA

int,

stopA

*bool)

{

for

i

:=

0;

i

<

countA;

i++

{

valueG

=

valueG

+

2

}

*stopA

=

true}

func

main()

{

go

routine1(10000,

&stop1)

go

routine1(10000,

&stop2)

for

{

if

stop1

&&

stop2

{

break

}

}

fmt.Printf("valueG:

%v\n",

valueG)}多次運(yùn)行結(jié)果不一致?并發(fā)安全共享安全就是保證在多任務(wù)并發(fā)處理時(shí)共享數(shù)據(jù)不會(huì)因共享沖突而導(dǎo)致錯(cuò)誤需要在編程中加上控制機(jī)制來(lái)保證同一時(shí)刻只能由一個(gè)任務(wù)來(lái)訪問(wèn)該數(shù)據(jù)當(dāng)變量或數(shù)據(jù)不會(huì)因多任務(wù)并發(fā)訪問(wèn)而出現(xiàn)異常時(shí),我們就稱之為是“共享安全”的目錄導(dǎo)航11.3使用通道類型實(shí)現(xiàn)安全的數(shù)據(jù)共享Contents通道(chan)類型Go語(yǔ)言內(nèi)置專門用于并發(fā)處理的數(shù)據(jù)類型:通道(chan)

chan類型可以理解成一個(gè)具備“共享安全”特性的“先入先出隊(duì)列”*大多數(shù)其他語(yǔ)言是在標(biāo)準(zhǔn)庫(kù)級(jí)別上支持線程的通道類型使用示例var

valueG

chan

intvar

stop1

bool

=

falsevar

stop2

bool

=

false

func

routine1(countA

int,

stopA

*bool)

{

for

i

:=

0;

i

<

countA;

i++

{

tmpC

:=

<-valueG

valueG

<-

(tmpC

+

2)

}

*stopA

=

true}

func

main()

{

valueG

=

make(chan

int,

1)

go

routine1(10000,

&stop1)

go

routine1(10000,

&stop2)

valueG

<-

0

for

{

if

stop1

&&

stop2

{

break

}

}

t.Printfln("valueG:

%v",

<-valueG)

close(valueG)注意->和<-操作符是“阻塞”的目錄導(dǎo)航11.4使用通道類型實(shí)現(xiàn)安全的數(shù)據(jù)共享Contents通道類型使用示例var

tokenG

chan

boolvar

stop1

bool

=

falsevar

stop2

bool

=

false

func

routine1(countA

int,

stopA

*bool)

{

for

i

:=

0;

i

<

countA;

i++

{

<-tokenG

valueG

=

valueG

+

2

tokenG

<-

false

}

*stopA

=

true}

func

main()

{

tokenG

=

make(chan

bool,

1)

go

routine1(10000,

&stop1)

go

routine1(10000,

&stop2)

tokenG

<-

false

for

{

if

stop1

&&

stop2

{

break

}

}

t.Printfln("valueG:

%v",

valueG)

close(tokenG)獲取到令牌的任務(wù)才能訪問(wèn)某些數(shù)據(jù)訪問(wèn)完畢之后交回令牌供其他任務(wù)使用目錄導(dǎo)航11.5使用通道實(shí)現(xiàn)多任務(wù)的歸并Contents多任務(wù)合并

并發(fā)編程中,主任務(wù)將任務(wù)拆分成子任務(wù)并等待所有子任務(wù)完成之后再進(jìn)行下一步處理的過(guò)程稱作“多任務(wù)的歸并(或合并)”,英文中常用join來(lái)表示合并任務(wù)的主控線程//

調(diào)用多個(gè)addRoutine函數(shù)實(shí)現(xiàn)多goroutine計(jì)算累加和的函數(shù)//

將各個(gè)goroutine計(jì)算的結(jié)果之和加起來(lái)就是最終的總和func

addByGoroutine(countA

int)

float64

{

sumT

:=

0.0

//

lenT是每個(gè)goroutine需要計(jì)算的次數(shù)

lenT

:=

countA

/

goroutineCount

//

leftT是平均非給每個(gè)goroutine后還剩余需要計(jì)算的次數(shù)

leftT

:=

countA

-

(countA/goroutineCount)*goroutineCount

//

第一個(gè)goroutine將多計(jì)算leftT次,即lenT+leftT次

go

addRoutine(lenT

+

leftT)

//

其他goroutine將計(jì)算lenT次

for

i

:=

1;

i

<

goroutineCount;

i++

{

go

addRoutine(lenT)

}

//

從通道循環(huán)讀取resultBuffer中的值,直到讀滿足夠的個(gè)數(shù)

for

i

:=

0;

i

<

goroutineCount;

i++

{

sumT

+=

<-resultBuffer

}

//

返回最終的計(jì)算結(jié)果

return

sumT}此處將是阻塞地讀取目錄導(dǎo)航11.6用select實(shí)現(xiàn)多通道的歸并Contents通過(guò)select監(jiān)聽(tīng)多個(gè)通道//

調(diào)用多個(gè)addRoutine1函數(shù)和多個(gè)addRoutine2實(shí)現(xiàn)各自累加和并將兩個(gè)累加和求相除結(jié)果的函數(shù)func

addByGoroutine(countA

int)

float64

{

sumT1

:=

0.0

sumT2

:=

0

lenT

:=

countA

/

goroutineCount//

lenT是每個(gè)goroutine需要計(jì)算的次數(shù)

leftT

:=

countA

-

(countA/goroutineCount)*goroutineCount

//

第一個(gè)goroutine將多計(jì)算leftT次,即lenT+leftT次

//

addRoutine1和addRoutine2都將被運(yùn)行成同樣個(gè)數(shù)的goroutine

go

addRoutine1(lenT

+

leftT)

go

addRoutine2(lenT

+

leftT)

for

i

:=

1;

i

<

goroutineCount;

i++

{//

其他goroutine將計(jì)算lenT次

go

addRoutine1(lenT)

go

addRoutine2(lenT)

}

//

從通道循環(huán)讀取resultBuffer1或resultBuffer2中的值,直到讀滿足夠的個(gè)數(shù)(應(yīng)為2

*

goroutineCount個(gè))

var

tmpF

float64

var

tmpC

int

for

i

:=

0;

i

<

goroutineCount*2;

i++

{

select

{

case

tmpF

=

<-resultBuffer1:

sumT1

+=

tmpF

case

tmpC

=

<-resultBuffer2:

sumT2

+=

tmpC

}

}

return

float64(sumT2)

/

sumT1//

返回最終的計(jì)算結(jié)果,為了計(jì)算類型一致,需要強(qiáng)制類型轉(zhuǎn)換}尤其適合監(jiān)聽(tīng)多個(gè)不同類型的通道時(shí)目錄導(dǎo)航11.7select中實(shí)現(xiàn)超時(shí)中止Contents通過(guò)select監(jiān)聽(tīng)多個(gè)通道

select

{

case

tmpF

=

<-resultBuffer1:

sumT1

+=

tmpF

case

tmpC

=

<-resultBuffer2:

sumT2

+=

tmpC

case

<-time.After(3

*

time.Second):

timeoutFlag

=

true

}time.After將返回一個(gè)定時(shí)觸發(fā)的chan類型值目錄導(dǎo)航11.8用單向通道自定義超時(shí)函數(shù)Contents單向通道var

c1

chan<-

int

//

定義一個(gè)只能寫(xiě)的通道

c1

=

make(chan<-

int,

10)

//

為只寫(xiě)通道設(shè)定容量//

直接簡(jiǎn)化式聲明一個(gè)只讀通道并設(shè)置容量

c2

:=

make(<-chan

float64,

10)

通過(guò)select監(jiān)聽(tīng)多個(gè)通道//

休眠指定的秒數(shù)后,向通道中寫(xiě)入一個(gè)數(shù)值表示超時(shí)(數(shù)值本身不重要)//

chanA是只能寫(xiě)入的單向通道func

realTimeout1(secondsA

time.Duration,

chanA

chan<-

bool)

{

time.Sleep(secondsA

*

time.Second)

chanA

<-

true}

//

僅用于新建一個(gè)通道后啟動(dòng)真正的超時(shí)routine,并將該通道返回讓select等待通道中有值func

timeout1(secondsA

time.Duration)

<-chan

bool

{

chan1

:=

make(chan

bool,

1)

//

傳入realTimeout1的chan1被強(qiáng)制轉(zhuǎn)換為只寫(xiě)通道類型

go

realTimeout1(secondsA,

(chan<-

bool)(chan1))

return

(<-chan

bool)(chan1)//

返回時(shí)將chan1強(qiáng)制轉(zhuǎn)換為只讀通道類型}…

select

{

case

tmpC

:=

<-resultBuffer1G:

totalSumT

+=

tmpC

case

tmpC

:=

<-resultBuffer2G:

totalSumT

+=

tmpC

case

<-timeout1(2):

//

超時(shí)時(shí)間是2秒

totalSumT

=

0

break

ForLabel

//

直接跳出循環(huán)而不是select結(jié)構(gòu)

}是chan類型值就可以select目錄導(dǎo)航11.9使用sync包進(jìn)行傳統(tǒng)的并發(fā)處理Contents用sync.WaitGroup實(shí)現(xiàn)goroutine歸并var

groupG

sync.WaitGroup

func

addRoutine(countA

int)

{

defer

groupG.Done()

for

i

:=

0;

i

<

countA;

i++

{

valueG

=

valueG

+

2

}}

groupG.Add(2)

go

addRoutine(tim

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論