goroutine的使用緩存
//Learn_Go/main.go package main import ( "fmt" "time" ) func demo(count int) { for i :=1; i < 10; i++{ fmt.Println(count,":",i) } } func main() { for i :=1; i < 10; i++{ go demo(i) } //添加休眠時間等待goroutine執行結束 time.Sleep(3e9) }
WaitGroup直譯爲等待組,其實就是計數器,只要計數器中有內容將一直阻塞安全
WaitGroup有三種方法併發
//Learn_Go/main.go package main import ( "fmt" "sync" ) func main() { var wg sync.WaitGroup wg.Add(5) for i := 0; i < 5; i++{ go func(j int) { fmt.Println("第",j,"次執行") wg.Done() }(i) } wg.Wait() fmt.Println("程序結束") }
(1)互斥鎖函數
能夠使用sync.Mutex對內容加鎖,互斥鎖的使用場景spa
(2)讀寫鎖線程
Go語言中的map不是線程安全的,多個gouroutine同時操做會出現錯誤blog
RWMutex能夠添加多個讀鎖或者一個寫鎖,讀寫鎖不能同時存在進程
map在併發下讀寫就須要結合讀寫鎖完成同步
互斥鎖表示鎖的代碼同一時間只能有一個goroutine運行,而讀寫鎖表示在鎖範圍內數據的讀寫操做string
//Learn_Go/main.go package main import ( "fmt" "sync" ) func main() { var rwm sync.RWMutex var wg sync.WaitGroup wg.Add(10) m := make(map[int]int) for i := 0; i < 10; i++{ go func(j int) { rwm.Lock() m[j] = j fmt.Println(m) rwm.Unlock() wg.Done() }(i) } wg.Wait() fmt.Println("程序結束") }
channel是進程內通訊方式,每一個channel只能傳遞一個類型的值,這個類型須要在聲明channel時指定
channel在Go中主要的兩個做用:同步和通訊
(1)聲明channel的語法
(2)操做channel的語法
(3)不管是向channel存數據仍是取數據都會阻塞
//Learn_Go/main.go package main import "fmt" func main() { ch := make(chan int) go func() { fmt.Println("執行") ch <- 111 }() a := <- ch fmt.Println(a) fmt.Println("程序結束") }
(4)使用channel實現gouroutine之間通訊
//Learn_Go/main.go package main import "fmt" func main() { ch1 := make(chan string) ch2 := make(chan int) go func() { ch1 <- "derek" ch2 <- 111 }() go func() { content := <- ch1 fmt.Println("取出數據:",content) //取出數據: derek ch2 <- 222 }() a := <- ch2 b := <- ch2 fmt.Println(a,b) //111 222 fmt.Println("程序結束") }
(5)能夠使用for range獲取channel中內容
//Learn_Go/main.go package main import "fmt" func main() { ch1 := make(chan int) ch2 := make(chan int) go func() { for i := 0; i<10;i++{ ch1 <- i } ch2 <- 222 }() go func() { for n := range ch1{ fmt.Println(n) } }() <- ch2 fmt.Println("程序結束") }
select執行過程
//Learn_Go/main.go package main import "fmt" func main() { ch1 := make(chan int,2) //有緩存的channel ch2 := make(chan int,3) ch1 <- 111 ch2 <- 222 select { case a := <-ch1: fmt.Println(a) case b := <-ch2: fmt.Println(b) default: fmt.Println("錯誤") } }
select多和for循環結合使用
//Learn_Go/main.go package main import "fmt" func main() { ch := make(chan int) for i := 0; i < 10;i++{ go func(j int) { ch <- j }(i) } //用for循環一直接受 for { select { case a := <- ch: fmt.Println(a) default: } } }