介紹
線程:輕量級(jí)進(jìn)程
攜程:輕量級(jí)線程
并發(fā)
協(xié)程
mac活動(dòng)監(jiān)視器=任務(wù)管理器
線程:進(jìn)程中的執(zhí)行路徑
package main
import "fmt"
//9
func main() {
/*
一個(gè)goroutine打印數(shù)字缎岗,另外一個(gè)goroutine打印字母耳幢,觀察運(yùn)行結(jié)果
*/
//1. 先創(chuàng)建并啟動(dòng)子goroutine默穴,執(zhí)行printNum()
go printNum()
//2. main打印字母
for i:=1;i<=100;i++ {
fmt.Printf("\t主goroutine打印字母:A %d\n",i)
}
fmt.Println("main over...")
}
func printNum(){
for i:=1;i<=100;i++ {
fmt.Printf("子goroutine打印數(shù)字:%d\n",i)
}
}
主goroutine結(jié)束直颅,程序就結(jié)束了,不管子goroutine讹蘑,可以用管道通信
與函數(shù)不同末盔,所以寫(xiě)了返回值也沒(méi)有用
啟動(dòng)多個(gè)goroutine
并發(fā)模型
runtime包
類(lèi)似與虛擬機(jī),管理內(nèi)存
package main
import (
"fmt"
"runtime"
"time"
)
//10
func main() {
//獲取goroot目錄
fmt.Println("GOROOT---->",runtime.GOROOT()) //GOROOT----> /usr/local/go
//獲取操作系統(tǒng)
fmt.Println("os/platform---->",runtime.GOOS) //os/platform----> darwin,mac系統(tǒng)
//獲取邏輯cpu的數(shù)量
fmt.Println("邏輯CPU的數(shù)量---->",runtime.NumCPU()) //邏輯CPU的數(shù)量----> 8
//設(shè)置cpu數(shù)量座慰,不要亂寫(xiě)陨舱,寫(xiě)當(dāng)前邏輯cpu數(shù)量就行,最好寫(xiě)在init函數(shù)
//n := runtime.GOMAXPROCS(16)
//fmt.Println(n)
//gosched讓出當(dāng)前時(shí)間片版仔,讓別的goroutine先執(zhí)行
go func(){
for i := 0; i < 5; i++ {
fmt.Println("goroutine...")
}
}()
for i := 0; i < 5; i++ {
//讓出時(shí)間片游盲,先讓別的goroutine執(zhí)行
runtime.Gosched()
fmt.Println("main...")
}
//創(chuàng)建goroutine
go func() {
fmt.Println("goroutine開(kāi)始")
//調(diào)用fun
fun()
fmt.Println("goroutine結(jié)束")
}()
//睡一會(huì)
time.Sleep(3 * time.Second)
}
func fun(){
defer fmt.Println("defer...")
// return //終止函數(shù)
runtime.Goexit() //終止當(dāng)前的goroutine
fmt.Println("fun函數(shù)")
}
臨界資源的安全問(wèn)題
package main
import (
"fmt"
"time"
)
//11
func main() {
/*
臨界資源
*/
a := 1
go func() {
a = 2
fmt.Println("goroutine中a:",a)
}()
a = 3
time.Sleep(1)
fmt.Println("main goroutine...",a)
}
package main
import (
"fmt"
"math/rand"
"time"
)
//11
func main() {
/*
臨界資源
*/
a := 1
go func() {
a = 2
fmt.Println("goroutine中a:",a)
}()
a = 3
time.Sleep(1)
fmt.Println("main goroutine...",a)
/*
4個(gè)goroutine,模擬4個(gè)售票口
*/
go saleTickets("售票口1")
go saleTickets("售票口2")
go saleTickets("售票口3")
go saleTickets("售票口4")
time.Sleep(5 * time.Second)
}
//全局變量
var ticket = 10
func saleTickets(name string) {
for{
if ticket > 0 {
rand.Seed(time.Now().UnixNano())
time.Sleep(time.Duration(rand.Intn(1000))*time.Millisecond)
fmt.Println(name,"售出",ticket)
ticket--
}else {
fmt.Println(name,"售罄蛮粮,沒(méi)有票了益缎。。")
break
}
}
}
不鼓勵(lì)通過(guò)共享內(nèi)存通信然想,鼓勵(lì)通過(guò)通信來(lái)共享內(nèi)存
channel
sync包下的WaitGroup同步等待組
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup //創(chuàng)建同步等待組的對(duì)象
//11
func main() {
/*
waitgroup:同步等待組
Add()链峭,設(shè)置等待組中要執(zhí)行的子 goroutine 的數(shù)量
Wait(),讓主goroutine等待
*/
wg.Add(2)
go fun1()
go fun2()
//無(wú)輸出
fmt.Println("main進(jìn)入阻塞又沾,等待wg的子groutine結(jié)束")
wg.Wait()
fmt.Println("main阻塞解除")
}
func fun1(){
for i := 1; i < 10; i++ {
fmt.Println("fun1打印 a", i)
}
wg.Done() //給wg等待組count數(shù)值減1 == add(-1)
}
func fun2(){
defer wg.Done()
for i := 1; i < 10; i++ {
fmt.Println("\tfun2打印 b", i)
}
}
如果沒(méi)有wg.Done()
如果是1,隨便抓一個(gè)
互斥鎖
互斥鎖熙卡、讀寫(xiě)鎖
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var wg sync.WaitGroup
//13
func main() {
/*
4個(gè)goroutine杖刷,模擬4個(gè)售票口
*/
wg.Add(4)
go saleTickets2("售票口1")
go saleTickets2("售票口2")
go saleTickets2("售票口3")
go saleTickets2("售票口4")
wg.Wait()
fmt.Println("main over")
}
//全局變量
var ticket = 10
var mutex sync.Mutex //創(chuàng)建鎖
func saleTickets2(name string) {
rand.Seed(time.Now().UnixNano())
defer wg.Done()
for{
//上鎖
mutex.Lock()
if ticket > 0 {
time.Sleep(time.Duration(rand.Intn(1000))*time.Millisecond)
fmt.Println(name,"售出",ticket)
ticket--
}else {
mutex.Unlock() //條件不滿足也要解鎖
fmt.Println(name,"售罄,沒(méi)有票了驳癌。滑燃。")
break
}
//解鎖
mutex.Unlock()
}
}
建議使用defer語(yǔ)句解鎖
讀寫(xiě)鎖
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
var rwMutex *sync.RWMutex
//14
func main() {
/*
讀寫(xiě)鎖
*/
rwMutex = new(sync.RWMutex)
//wg.Add(2)
//
////讀操作可以同時(shí)進(jìn)行
//go readData(1)
//go readData(2)
wg.Add(3)
go writeData(1)
go readData(2)
go writeData(3)
wg.Wait()
fmt.Println("main over")
}
func writeData(i int){
defer wg.Done()
fmt.Println(i,"開(kāi)始寫(xiě):write start。颓鲜。")
rwMutex.Lock() //讀操作上鎖
fmt.Println(i,"正在寫(xiě)")
time.Sleep(1 * time.Second)
rwMutex.Unlock() //讀操作解鎖
fmt.Println(i,"寫(xiě)結(jié)束:write over")
}
func readData(i int){
defer wg.Done()
fmt.Println(i,"開(kāi)始讀:read start表窘。。")
rwMutex.RLock() //讀操作上鎖
fmt.Println(i,"正在讀取")
time.Sleep(1 * time.Second)
rwMutex.RUnlock() //讀操作解鎖
fmt.Println(i,"讀結(jié)束:read over")
}