一、goroutine

格式

1
2
3
4
5
6
// 引用外部 i 不安全
go func(i int) {
for {
fmt.Printf("goroutine :%d \n",i)
}
}(i)

关键字 go + 函数,是一种协程 Coroutine

  • 轻量级“线程”
  • 非抢占式多任务处理,由协程主动交出控制权
  • 编译器/解释器/虚拟机层面的多任务
  • 多个协程可以在一个或多个线程上运行
  • 不需要在定义时区分是不是异步
其他语言的协程
  • C++ :Boost.Coroutine
  • java 不支持
  • python :yield 关键字实现协程
goroutine 切换点
  • I/O,select

  • channel

  • 等待锁

  • 函数调用(有时)

  • runtime.Gosched()

二、channel(通道)

1
2
3
4
5
6
//创建 channel (一等公民)
c := make(chan int)
// <- 传值方向 1 送给 c
c <- 1
// <- 传值方向 c 送给 n
n := <-c

不要通过共享内存来通信,通过通信来共享内存

WaitGroup

通过共用系统 WaitGroup 等待 channel 任务做完

1
2
3
4
var wg sync.WaitGroup
wg.Add(20)//添加等待任务数量
wg.done()//任务结束通知
wg.Wait()//等待结束通知select

三、 select 进行调度

1
2
3
4
5
6
7
8
select {
case n := <-c1:
values = append(values,n)
case n := <-c2:
values = append(values,n)
case activeWorker <- activeValue:
values = values[1:]
}

四、传统的同步机制

  • WaitGroup
  • Mutex
  • Cond
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
type atomicInt struct {
value int
lock sync.Mutex //同步保护
}
func (a *atomicInt) increment() {
fmt.Println("safe increment")
func(){
a.lock.Lock()//加锁
defer a.lock.Unlock()//释放锁
a.value++
}()
}
func (a *atomicInt) get() int {
a.lock.Lock()//加锁
defer a.lock.Unlock()//释放锁
return a.value
}

五、CSP 模型

CSP(Communicating Sequential Process)模型是上个世纪七十年代提出的,用于描述两个独立的并发实体通过共享的通讯 channel(管道)进行通信的并发模型。 CSP中channel是第一类对象,它不关注发送消息的实体,而关注与发送消息时使用的channel。