Goroutine
在一个函数前加上go关键字就能为一个函数创建一个协程来运行
Go 协程有这种调度机制:
循环并不会等待打印操作执行完再创建下一个协程,而是直接进行下一个循环,立刻创建新协程,一共创建了10个协程。而这10个协程的调度时机又是不确定的
func pr(i int) {
fmt.Println("goroutine : ", i)
}
func main() {
for i := 1; i <= 10; i++ {
go pr(i)
}
time.Sleep(time.Second)
}
Channel
Channel创建的方法:
- ch1 := make(chan int) // 无缓冲通道
- ch2 := make(chan int, 2) // 有缓冲通道
通过通信共享内存:
func main() {
ch1 := make(chan int)
ch2 := make(chan int, 2)
go func() {
defer close(ch1)
for i := 1; i <= 10; i++ {
ch1 <- i
}
}()
go func() {
defer close(ch2)
for i := range ch1 {
ch2 <- i * i
}
}()
for i := range ch2 {
println(i)
}
}
由输出结果可知实现了并发安全
CPU在同一时间只能运行一个任务,我们看起来好像是同时在运行的,这个就叫做并发。而并行则是在同一时刻,执行多个任务。
Lock && WaitGroup
互斥锁:
使用互斥锁能够保证同一时间有且只有一个goroutine进入临界区,其他的goroutine则在等待锁;当互斥锁释放后,等待的goroutine才可以获取锁进入临界区,多个goroutine同时等待一个锁时,唤醒的策略是随机的。
通过暴力方法休眠
var (
x int
lock sync.Mutex
)
func withLock() {
for i := 1; i <= 2000; i++ {
lock.Lock()
x++
lock.Unlock()
}
}
func withoutLock() {
for i := 1; i <= 2000; i++ {
x++
}
}
func main() {
x = 0
for i := 1; i <= 5; i++ {
go withLock()
}
time.Sleep(time.Second)
fmt.Println(x)
x = 0
for i := 1; i <= 5; i++ {
go withoutLock()
}
time.Sleep(time.Second)
fmt.Println(x)
}
WaitGroup:
- add开启协程
- Done在一个子协程结束后计数器--
- wait在计数器归零时进行阻塞
var num sync.WaitGroup
func pr(i int) {
defer num.Done()
println("Hello ", i)
}
func main() {
num.Add(10)
for i := 1; i <= 10; i++ {
go pr(i)
}
num.Wait()
}
标签:依赖,协程,进阶,int,make,goroutine,chan,func,Go
From: https://www.cnblogs.com/Aidan347/p/17062206.html