進程和線程
A。進程是程序在操做系統中的一次執行過程,系統進行資源分配和調度的一個獨立單位。
B。線程是進程的一個執行實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。
C。一個進程能夠建立和撤銷多個線程;同一進程中的多個線程之間能夠併發執行。
併發和並行
併發:多線程程序在一個核的cpu上運行
並行:多線程程序在多個核的cpu上運行
舉例。。一個媽給一個碗給多個小孩餵飯,,是併發
一個媽給每一個小孩一人一個碗,就是並行
併發 並行安全
協程和線程
協程:獨立的棧空間,共享堆空間,調度由用戶本身控制,本質上有點相似於用戶級協程,這些用戶級線程的調度也是本身實現的。
線程:一個線程上能夠跑多個協程,協程是輕量級的線程。
例子多線程
package main import ( "fmt" "time" ) func test() { var i int for { fmt.Println(i) time.Sleep(time.Second) i++ } } func main() { go test() //起一個協程執行test() for { fmt.Println("i : runnging in main") time.Sleep(time.Second ) } }
-併發
--ide
設置Golang運行的cpu核數。函數
1.8版本以上,默認跑多個核ui
package main import ( "fmt" "runtime" ) func main() { num := runtime.NumCPU() runtime.GOMAXPROCS(num) fmt.Println(num) }
併發計算spa
package main import ( "fmt" "sync" "time" ) var ( m = make(map[int]uint64) lock sync.Mutex ) type task struct { n int } func calc(t *task) { var sum uint64 sum = 1 for i := 1; i < t.n; i++ { sum *= uint64(i) } fmt.Println(t.n, sum) lock.Lock() m[t.n] = sum lock.Unlock() } func main() { for i := 0; i < 16; i++ { t := &task{n: i} go calc(t)//併發執行,誰快誰先出 } time.Sleep(10 * time.Second) //lock.Lock() //for k, v := range m { // fmt.Printf("%d!=%v\n", k, v) //} //lock.Unlock() }
channel概念
a。相似unix中的管道(pipe)
b.先進先出
c。線程安全,多個goroutine同時訪問,不須要枷鎖
d。channel是有類型的,一個整數的channel只能存整數
channel聲明操作系統
var name chan string var age chan int var mapchan chan map[string]string var test chan student var test1 chan *student
channel初始化線程
使用make進行初始化 var test chan int test = make(chan int,10) var test chan string test=make(chan string,10)
channel基本操做unix
從channel讀取數據
var testChan chan int testChan = make(chan int, 10) var a int a = <-testChan
-從channel寫入數據
var testChan chan int testChan = make(chan int, 10) var a int = 10 testChan <- a
第一個例子
package main import "fmt" type student struct { name string } func main() { var stuChan chan *student stuChan = make(chan *student, 10) stu := student{name: "stu001"} stuChan <- &stu var stu01 interface{} stu01 = <-stuChan var stu02 *student stu02, ok := stu01.(*student) if !ok { fmt.Println("can not convert") return } fmt.Println(stu02) }
package main import ( "fmt" "time" ) //起一個讀的協程 func write(ch chan int) { for i := 0; i < 1000; i++ { ch <- i } } func read(ch chan int) { for { var b int b = <-ch fmt.Println(b) } } func main() { intChan := make(chan int, 10) go write(intChan) go read(intChan) time.Sleep(10 * time.Second) }
讀,取,字符串
package main import ( "fmt" "time" ) func sendData(ch chan string) { ch <- "Washington" ch <- "Tripoli" ch <- "London" ch <- "Beijing" ch <- "Tokio" } func getData(ch chan string) { var input string for { input = <-ch fmt.Println(input) } } func main() { ch := make(chan string) go sendData(ch) go getData(ch) time.Sleep(3 * time.Second) }
只能放一個元素的testChan var testChan chan int testChan = make(chan int) var a int a = <-testChan
-
testChan是帶緩衝區的chan,一次能夠放10個元素
var testChan chan int testChan = make(chan int, 10) var a int = 10 testChan <- a
-
package main import ( "fmt" "sync" "time" ) var ( m = make(map[int]uint64) lock sync.Mutex ) type task struct { n int } func calc(t *task) { var sum uint64 sum = 1 for i := 1; i < t.n; i++ { sum *= uint64(i) } fmt.Println(t.n, sum) lock.Lock() m[t.n] = sum lock.Unlock() } func main() { for i := 0; i < 16; i++ { t := &task{n: i} go calc(t) } time.Sleep(10 * time.Second) lock.Lock() for k, v := range m { fmt.Printf("%d!=%v\n", k, v) } lock.Unlock() }
package main import ( "fmt" ) func calc(taskChan chan int, resChan chan int, exitChan chan bool) { for v := range taskChan { flag := true for i := 2; i < v; i++ { if v%i == 0 { flag = false break } } if flag { resChan <- v } } fmt.Println("exit") exitChan <- true } func main() { intChan := make(chan int, 1000) resultChan := make(chan int, 1000) exitChan := make(chan bool, 8) go func() { for i := 0; i < 10000; i++ { intChan <- i } close(intChan) }() for i := 0; i < 8; i++ { go calc(intChan, resultChan, exitChan) } //等待全部計算的goroutine所有退出 go func() { for i := 0; i < 8; i++ { <-exitChan fmt.Println("wait goroute", i, "exited") } close(resultChan) }() for v := range resultChan { fmt.Println(v) } }
package main import "fmt" func send(ch chan int, exitChan chan struct{}) { for i := 0; i < 10; i++ { ch <- i } close(ch) var a struct{} exitChan <- a } func recv(ch chan int, exitChan chan struct{}) { for { v, ok := <-ch if !ok { break } fmt.Println(v) } var a struct{} exitChan <- a } func main() { var ch chan int ch = make(chan int, 10) exitChan := make(chan struct{}, 2) go send(ch, exitChan) go recv(ch, exitChan) var total = 0 for _ = range exitChan { total++ if total == 2 { break } } }
package main import "fmt" func main() { var ch chan int ch = make(chan int, 10) for i := 0; i < 10; i++ { ch <- i } close(ch) for { var b int b, ok := <-ch //檢測管道是否關閉 if ok == false { fmt.Println("chan is close") break } fmt.Println(b) } }
1. 使用內置函數close進行關閉,chan關閉以後,for range遍歷chan中 已經存在的元素後結束 2. 使用內置函數close進行關閉,chan關閉以後,沒有使用for range的寫法 須要使用,v, ok := <- ch進行判斷chan是否關閉
只讀的聲明 Var 變量的名字 <-chan int Var readChan <- chan int 只寫的聲明 Var 變量的名字 chan<- int Var writeChan chan<- int
package main import "fmt" //只寫chan func send(ch chan<- int, exitChan chan struct{}) { for i := 0; i < 10; i++ { ch <- i } close(ch) var a struct{} exitChan <- a } //只讀chan func recv(ch <-chan int, exitChan chan struct{}) { for { v, ok := <-ch if !ok { break } fmt.Println(v) } var a struct{} exitChan <- a } func main() { var ch chan int ch = make(chan int, 10) //初始化chan exitChan := make(chan struct{}, 2) go send(ch, exitChan) go recv(ch, exitChan) var total = 0 for _ = range exitChan { total++ if total == 2 { break } } }
不阻塞
package main import "fmt" import "time" func main() { var ch chan int ch = make(chan int, 10) ch2 := make(chan int, 10) go func() { var i int for { ch <- i time.Sleep(time.Second) ch2 <- i * i time.Sleep(time.Second) i++ } }() for { select { case v := <-ch: fmt.Println(v) case v := <-ch2: fmt.Println(v) case <-time.After(time.Second): fmt.Println("get data timeout") time.Sleep(time.Second) } } }