目录
进程和线程
进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。
线程是进程的一个执行实体,是cpu调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
一个进程可以创建和撤销多个线程;同一个进程中的多个线程之间可以并发执行。
并发和并行
多线程程序在一个核的CPU上运行,就是并发。
多线程程序在多个核的CPU上运行,就是并行。
协程和线程
协程:独立的栈空间,共享堆空间,调度由用户自己控制,本质上有点类似于用户级线程,这些用户级线程的调度也是自己实现的。
线程:一个线程上可以跑多个协程,协程是轻量级的线程。
不同gorountine之间如何进行通讯?
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)
}
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()
}
b. Channel
类似于unix中的管道;先进先出;线程安全,多个goroutine同时访问,不需要加锁;channel是有类型的,一个整数的channel只能存放整数。
声明:var 变量名 chan 类型 (注: channel一定得初始化)
channel基础:实例代码如下:
package main
import (
"fmt"
)
type student struct {
name string
}
func main() {
var stuChan chan interface{}
stuChan = make(chan interface{}, 10) //使用make初始化
stu := student{name: "stu01"}
stuChan <- &stu //从channel写入数据
var stu01 interface{}
stu01 = <-stuChan
var stu02 *student
stu02, ok := stu01.(*student)
if !ok {
fmt.Println("can not convert")
}
fmt.Println(stu02)
}
channel堵塞:
由于chan声明时缓存区大小为5,故达到5个时只能读出再写进。
package main
import (
"fmt"
"time"
)
func write(ch chan int) {
for i := 0; i < 100; i++ {
ch <- i
fmt.Println("put data:", i)
}
}
func read(ch chan int) {
for {
var b int
b = <-ch
fmt.Println(b)
time.Sleep(time.Second)
}
}
func main() {
intChan := make(chan int, 5)
go write(intChan)
go read(intChan)
time.Sleep(10 * time.Second)
}
channel读写同步
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) //同来存储所有gorounte是否计算完毕
go func() {
for i := 0; i < 1000; i++ {
intChan <- i
}
close(intChan)
}()
for i := 0; i < 8; i++ {
go calc(intChan, resultChan, exitChan)
}
//等待所有计算得groutine全部退出
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 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)
}
}