版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 租賃車輛合同協(xié)議文本
- 大客戶采購(gòu)合同的監(jiān)管措施
- 瓦工工種勞務(wù)分包合作協(xié)議
- 網(wǎng)絡(luò)技術(shù)服務(wù)合同示范文本樣本
- 個(gè)性化印刷采購(gòu)協(xié)議
- 電子行業(yè)專用包裝材料購(gòu)銷合同
- 拖車運(yùn)輸服務(wù)協(xié)議
- 工程分包所需勞務(wù)合同
- 房屋買賣合同簽訂前的房屋質(zhì)量檢查
- 網(wǎng)絡(luò)打印機(jī)選購(gòu)協(xié)議
- 課間十分鐘 文明安全行
- VDA6.5產(chǎn)品審核培訓(xùn)資料
- 電網(wǎng)公司基建安全管理規(guī)定
- 【苯乙烯-丙烯酸酯乳液聚合裝置工藝設(shè)計(jì)與實(shí)現(xiàn)(論文)】
- 2022年安徽省公務(wù)員錄用考試《行測(cè)》題
- 基于MATLAB的硬幣計(jì)數(shù)設(shè)計(jì)
- 工程力學(xué)-國(guó)防科技大學(xué)中國(guó)大學(xué)mooc課后章節(jié)答案期末考試題庫(kù)2023年
- 料神外貿(mào)老鳥(niǎo)之路201407全整理
- 小學(xué)數(shù)學(xué)教師個(gè)人三年發(fā)展規(guī)劃(5篇)
- 神經(jīng)內(nèi)科年度發(fā)展規(guī)劃
- 煤礦安全責(zé)任清單
評(píng)論
0/150
提交評(píng)論