golang 并发
Golang 并发[*]并行 指的是在同一时刻 有多条指令在多个CPU处理器上同时执行 2个任务2个窗口需要硬件支持
[*]并发是指在同一时刻 只能有一条指令 单多个进程指令快速轮换执行 2个队伍1个窗口 要求提升软件能力
Golang 并发优势
[*]go 从底层就支持并发
[*]简化了并发程序的编写方法
Goroutine 是什么
[*]它是go 并发设计的核心
[*]goroutine就是协程,它比线程更小,十几个goroutine 在底层可能就是五六个线程
[*]go 语言内部实现了goroutine的内存共享,执行goroutine只需极少的栈内存(大概4-5KB)
创建goroutine
[*]只需要在语句前添加go 关键字即可
package main
import (
"fmt"
"time"
)
//测试协程
//循环打印内容
func newTask() {
i := 0
for {
i++
fmt.Printf("new goroutine\:i=%d\n", i)
time.Sleep(1 \* time.Second)
}
}
//main()相当于是主协程
func main() {
//启动子协程
go newTask()
i := 0
for {
i++
fmt.Printf("main goroutine\:i=%d\n", i)
time.Sleep(1 \* time.Second)
}
}
[*]开发人员无需了解任何执行细节,调度器会自动将其安排到合适的系统线程上运行
[*]如果主协程推出,所有子进程协程都会退出
package main
import (
"fmt"
"time"
)
//main()相当于是主协程
func main() {
//匿名子协程
go func() {
i := 0
for {
i++
fmt.Println("子协程 i=", i)
time.Sleep(1 \* time.Second)
}
}()
i := 0
for {
i++
fmt.Println("主协程 i=", i)
time.Sleep(1 \* time.Second)
//主协程第二次后退出
if i == 2 {
break
}
}
}
[*]程序没任何输出,也不报错
package main
import (
"fmt"
"time"
)
//main()相当于是主协程
func main() {
//匿名子协程
go func() {
i := 0
for {
i++
fmt.Println("子协程 i=", i)
time.Sleep(1 \* time.Second)
}
}()
}runtime 包
[*]runtime.Gosched(): 用于让出CPU时间片,调度器重新安排任务调度,还是有几率分配到它的
package main
import (
"fmt"
"runtime"
)
func main() {
//匿名子协程
go func(s string) {
for i := 0; i < 2; i++ {
fmt.Println(s)
}
}("world")
//主协程
for i := 0; i < 2; i++ {
runtime.Gosched()
fmt.Println("hello")
}
}
[*]runtime.Goexit() 立即终止当前协程
package main
import (
"fmt"
"time"
"runtime"
)
func main() {
//匿名子协程
go func() {
defer fmt.Println("A.defer")
//匿名函数
func() {
defer fmt.Println("B.defer")
//此时只有defer执行
runtime.Goexit()
fmt.Println("B")
}()
fmt.Println("A")
}()
for {
time.Sleep(time.Second)
}
}
[*]runtime.GOMAXPROCS(): 设置并行计算的CPU核数,返回之前的值
package main
import (
"runtime"
"fmt"
)
func main() {
n := runtime.GOMAXPROCS(3)
fmt.Println("n=%d\n",n)
//循环执行2个
for{
go fmt.Print(0)
fmt.Print(1)
}
}channel
[*]goroutine运行在相同的地址空间,因此访问共享内存必须做好同步,处理好线程安全
[*]goroutine奉行通过通信来共享内存,而不是共享内存通信
[*]channel 是一个引用类型 用于多个goroutine 通讯 其内部实现了同步,确保并发安全
Channel基本使用
<ul>Channel 可以用内置make() 创建
定义一个channel 也需要定义发送到channel值类型
make(chan 类型) // 无缓冲通道
make(chan 类型, 容量) // 有缓冲通道当capacity=0 时, channel 是无缓冲阻塞读写的,当capacity>0, channel 有缓冲,是非阻塞的,直到写满capacity个元素才阻塞写入
channel 通过操作符
页:
[1]