石岩网站设计,app拉新工作室,网页设计教程案例 杨松,网络工程师证什么协程
在Go语言中#xff0c;协程就是一种轻量的线程#xff0c;是并发编程的单元#xff0c;由Go来管理#xff0c;所以在GO层面的协程会更加的轻量、高效、开销更小#xff0c;并且更容易实现并发编程。
轻量级线程
Go语言中协程#xff08;线程#xff09;与传…什么协程
在Go语言中协程就是一种轻量的线程是并发编程的单元由Go来管理所以在GO层面的协程会更加的轻量、高效、开销更小并且更容易实现并发编程。
轻量级线程
Go语言中协程线程与传统系统层面的线程相比实在是太轻量了能小到2kb由于协程的轻量特性可以更高效地利用系统资源。相较于传统的线程协程的创建和销毁的开销更小使得程序更具有扩展性和性能优势。
Go自身管理
在 Go 中这些工作由运行时系统自动完成。这样我们就可以更专注于业务逻辑而不必过多关心底层线程管理的细节。
并发的基本单元
协程是并发编程的基本单元可以同时执行多个协程而它们之间的调度和切换由运行时系统负责。在程序中更容易实现高效的并发处理多个任务而无需显式地创建和管理线程。使用协程我们可以轻松地实现并发任务例如同时处理多个网络请求、执行后台任务等。由于协程的轻量特性可以创建数千甚至数百万个协程而不会造成系统负担。
使用通道通信
协程之间可以通过通道进行通信这是一种在协程之间安全地传递数据和同步操作的机制。通道是一种强大的工具用于协程之间的协作和数据传递。
协程的基本操作
创建协程
- 语法 go 函数(函数列表)package main import ( fmt time) func Hello() { fmt.Println(hello world)
} func main() { go Hello() fmt.Println(hello main) time.Sleep(10 * time.Second)
} 协程与主线程是并发执行的。 协程间通行
主要通过channel来实现的
package main import ( fmt
) func sendMessage(ch chan string, msg string) { ch - msg
} func main() { messagechan : make(chan string) go sendMessage(messagechan, Hello World) msg : -messagechan fmt.Println(msg)
}协程间的同步
使用sync包来实现的waitgroup 是用来计数信号量的
package main import ( fmt sync) func worker(id int, wg *sync.WaitGroup) { defer wg.Done() fmt.Printf(worker %d starting\n, id) fmt.Printf(worker %d done\n, id)
} func main() { var wg sync.WaitGroup for i : 1; i 10; i { wg.Add(1) go worker(i, wg) } wg.Wait() fmt.Printf(all workers done\n)
} waitgroup确保主线程等待所有协程完成 协程的错误处理
使用select语句和通道可以实现协程的错误处理
package main import ( fmt time) func dosomething(ch chan string) { time.Sleep(2 * time.Second) ch - hello world
} func main() { ch : make(chan string) go dosomething(ch) select { case msg : -ch: fmt.Println(msg) case -time.After(1 * time.Second): fmt.Println(timeout) }
} select 语句允许在多个通道操作中选择一个可用的操作可以用来处理协程的超时等情况。 协程的高级操作
协程池
协程池是一组预先创建的协程用于执行并发任务可以避免频繁创建和销毁协程的开销。使用缓冲通道来实现协程池
package main import ( fmt sync) func worker(id int, jobs -chan int, results chan- int) { for j : range jobs { fmt.Println(worker, id, started job, j) results - j * 2 }
} func main() { const numJobs 5 const numWorkers 3 jobs : make(chan int, numJobs) results : make(chan int, numJobs) var wg sync.WaitGroup for i : 1; i numWorkers; i { wg.Add(1) go func(i int) { defer wg.Done() worker(i, jobs, results) }(i) } for j : 1; j 5; j { jobs - j } close(jobs) go func() { wg.Wait() close(results) }() for result : range results { fmt.Println(result, result) }
}三个协程形成了协程池从任务通道 jobs 中获取任务处理后将结果发送到结果通道 results 超时控制
package main import ( fmt time) func dosomething(ch chan string) { time.Sleep(2 * time.Second) ch - hello world
} func main() { ch : make(chan string) go dosomething(ch) select { case msg : -ch: fmt.Println(msg) case -time.After(1 * time.Second): fmt.Println(timeout) }
} time.After 创建一个计时器如果在指定时间内没有从通道 ch 中接收到结果就会触发超时。 协程的取消
使用 context 包提供的上下文Context来实现协程的取消。
package main import ( context fmt time) func doSomething(ctx context.Context, ch chan string) { select { case -ctx.Done(): ch - task completed successfully case -time.After(1 * time.Second): ch - task timed out }
} func main() { ctx, cancel : context.WithCancel(context.Background()) defer cancel() ch : make(chan string) go doSomething(ctx, ch) time.Sleep(2 * time.Second) cancel() result : -ch fmt.Println(result)
}通过调用 cancel 函数取消协程的执行。