- 并发与并行: 并发: 并发是在一个程序中同时执行多个任务的能力。 并行: 并行是在同一时刻执行多个任务的能力 以下为Go语言的并发与并行的概念和用法: Go协程(goroutine) Go协程(goroutine):Go语言通过轻量级的用户态线程——协程(goroutine)来实现并发。使用关键字go可以创建一个协程,使其在后台运行,从而能够同时执行多个任务。相比系统线程,协程的创建和销毁代价较低,并且调度器能够在协程之间进行高效切换。 import ( "fmt" "time" )
func worker(num int) { for i := 0; i < 5; i++ { fmt.Printf("Worker %d: %0; i < 10; i++ { go worker(i) } // 等待所有协程执行完毕 time.Sleep(time.Second * 10) fmt.Println("Main: End") } 这个程序使用了go关键字来创建协程。每个协程都执行相同的函数worker,但是它们各自的num参数不同。在主函数中,使用一个循环创建了10个协程,并使用time.Sleep函数等待10秒钟,以确保所有协程都有时间执行完毕。
- CSP和通道(channel) Go语言的CSP(Communicating Sequential Processes)是一种并发编程模型,它描述了两个独立的并发实体通过共享的通信通道进行通信的并发模型。 在CSP中,通信通道被称为channel,它是第一类对象,即可以像变量一样传递和操作。实体通过向channel发送消息来通信,也可以从channel接收消息。 CSP模型的关键是关注channel,而不关注发送消息的实体。在Go语言中,goroutine对应CSP中的并发实体,而channel则对应CSP中的channel。
package main import ( "fmt" ) func producer(ch chan<- int) { for i := 0; i < 5; i++ { ch <- i // 将i发送到通道ch } close(ch) // 关闭通道ch } func consumer(ch <-chan int) { for num := range ch { fmt.Println(num) // 从通道ch接收数据并打印 } } func main() { ch := make(chan int) // 创建一个整型通道
go producer(ch) // 启动生产者协程,向通道发送数据
consumer(ch) // 在主协程中作为消费者,从通道接收数据
}
在这个例子中,定义了两个函数producer()和consumer(),分别作为生产者和消费者协程。producer()函数通过将0到4的整数发送到通道ch,然后关闭通道。consumer()函数从通道ch接收数据,并打印到控制台。 在main函数中,创建了一个整型通道ch,然后通过使用go关键字启动一个生产者协程producer(ch)和一个消费者协程consumer(ch)。这样,生产者和消费者协程可以并发执行,通过通道进行数据的同步和交互。运行该程序,0到4的整数被顺序打印出来。go充分的实现高并发
go可以在用户态上开很多个协程,协程是在KB级别的
在go中创建协程
在调用协程函数的前面添加go
go func(j int) { hello(j) }(i) go func(){
}() Channel make(chan 元素类型,[缓冲大小])
无缓冲通道 make(i int)
有缓冲通道 make(i int ,2)
通常提倡通过通道来实现数据的共享
通过通道来实现数据的共享
func CalSquare(){ src := make(chan int) dest :=make(chan ine,3) go func(){ defer closs(src) for i:=0;i<9;i++{ src<-i } }() go func(){ defer close(dast){ for i:=range src{ i<-i*i } } }() fot i:=range dest{ println(i) } } 并发安全 使用锁来进行数据的共享
var( x int64 lock sync.Mutex ) func addWithLock(){ for i:=0;i<2000;i++{ lock.Lock() x += i lock.Unlock() } } func addWithoutLock(){ for i := 0 ; i < 2000 ; i++ { x+=i } } func Add(){ x=0 for i:=0;i<5;i++{ go addWithLock() } time.Sleep(time.Second) println("WithLock",x) x=0 for i:=0;i<5;i++{ go addWithoutLock() } time.Sleep(time.Second) println("WithoutLock",x) } 会出现计算的错误 WaitGroup 是创建多个子协程的写法
通过计数来进行操作
func main(){ var wg sync.W }func ManyGoWait() { var wg sync.WaitGroup wg.Add(5) //创建5个字协程 for i := 0; i < 5; i++ { go func(j int) { defer wg.Done() //子协程完成,数量减1 hello(j) }(i) } wg.Wait() //协程等待运行完 }