




版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- T/CWAN 0029.3-2021鎳基焊接材料化學(xué)分析方法第3部分:氮含量測(cè)定惰性氣體熔融熱導(dǎo)法
- T/CSPSTC 7-2017企業(yè)標(biāo)準(zhǔn)自我聲明規(guī)范
- T/CSPSTC 127-2023城鎮(zhèn)排水管道封堵施工技術(shù)規(guī)程
- T/CSIQ 3101-2015陶瓷藝術(shù)品表面微觀結(jié)構(gòu)測(cè)試方法體視顯微鏡法
- T/CNFMA B031-2023戶外林業(yè)機(jī)械以鋰離子電池為動(dòng)力源的便攜式伐竹剪
- T/CNFA 016-2021辦公椅質(zhì)量安全等級(jí)評(píng)定
- T/CNESA 1201-2018壓縮空氣儲(chǔ)能系統(tǒng)集氣裝置工程設(shè)計(jì)規(guī)范
- T/CNCIA 01031-2023水泥基藝術(shù)涂料
- T/CMA CC-045-2020計(jì)量電子原始記錄通用規(guī)范
- T/CIQA 32-2022出入境生物安全消毒服務(wù)機(jī)構(gòu)質(zhì)量管理要求
- 數(shù)字化電力系統(tǒng)轉(zhuǎn)型-洞察闡釋
- 2025中國(guó)甲烷大會(huì):2024-2025全球甲烷控排進(jìn)展報(bào)告
- 小學(xué)四年級(jí)下冊(cè)語(yǔ)文期末考試試卷含答案共6套
- 2025各個(gè)班組安全培訓(xùn)考試試題含答案可下載
- 術(shù)后急性疼痛及個(gè)體化鎮(zhèn)痛
- 藥物動(dòng)力學(xué)與臨床相關(guān)考點(diǎn)試題及答案
- 動(dòng)態(tài)設(shè)計(jì)寶典C4D三維圖像設(shè)計(jì)與交互知到智慧樹(shù)期末考試答案題庫(kù)2025年青島工學(xué)院
- 幼兒園畢業(yè)典禮流程安排
- 2024年公安機(jī)關(guān)理論考試題庫(kù)500道附參考答案【基礎(chǔ)題】
- GB/T 196-2025普通螺紋基本尺寸
- MOOC 中國(guó)電影經(jīng)典影片鑒賞-北京師范大學(xué) 中國(guó)大學(xué)慕課答案
評(píng)論
0/150
提交評(píng)論