----------------------------------------- go 并发
//注解:go 语言天生为程序并发所设计,可以说go的强项就是在cpu并发上的处理。//go 语言层面就支持了并发。(不是一般高级语言的多线程并发,是系统级真实并发)//go 语言通过安全的通道发送和接受数据以实现同步//一般情况下,一个普通的桌面计算机跑十几二十几个线程就有点负载过大了,但是同样的硬件设备go可以轻松上K。
----------------------------------------- goroutine
//注解:go 并发设计的核心,goroutine在并发中起到的作用就是协程(CSP),但是它比线程更小。(协程=微线程)//go 不支持后台协程,意思就是主程序退出,协程跟着一起退出
func newTask() {for{
fmt.Println("new task ...")
time.Sleep(time.Second)//休眠1s
}
}
func main() {
go newTask()//新建一个协程,新建一个任务
for{
fmt.Println("main ...")
time.Sleep(time.Second)//休眠1s
}
}//result ://main...//new task ...//....
----------------------------------------- gosched
//注解:让出CPU时间片,让出当前 gorotine 的执行权限,//调度器安排其他等待任务运行,并在下次某个时候从该位置恢复执行。
func main() {
go func() {for i := 0; i < 5; i++{
fmt.Println("go")
}
}()for i := 0; i < 2; i++{
fmt.Println("hello")
}//这种情况,匿名函数未得到执行程序就结束了。//时间片案例演示代码,修改如下:
for i := 0.... {
runtime.Gosched()
fmt.Println("hello")
}//执行结果://go go ... hello ..
}
----------------------------------------- goexit
import "runtime"
//注解:终止所在的协程 (所在的协程不是当前函数)
func test() {
defer fmt.Println("ccccc")
runtime.Goexit()
fmt.Println("dddd")
}
func main() {
go func (){
fmt.Println("aaaa")
test()
fmt.Println("bbbb")
}for{
}//result://aaaa cccc
}
----------------------------------------- gomaxProcs
//注解:设置可以并行计算的 CPU 核数的最大值
import "runtime"func main() {
n := runtime.GOMAXProcs(1) //制定以1核运算
fmt.Println("n =", n)for{
go fmt.Print(1)
fmt.Print(0)
}//打印结果:11111.. 一大片, 00000...一大片//如果设置 GOMAXProcs(4) 为 4 核交叉效果更好
}
----------------------------------------- 资源争夺问题 channel
//注解:channel 也是一种数据类型,同步//语法:channel
var ch = make(chan int)//定义一个打印机,参数为字符串,按每个字符打印
func Printer(str string) {for _, data :=range str {
fmt.Printf("%c", data)
time.Sleep(time.Second)
}
fmt.Printf("\n")
}
func person1() {
Printer("loong print")
ch
}
func person2() {
Printer("make print")
}
func main() {//新建 2 个协程,代表 2 个人,2 个人同时使用打印机
go person1()
go person2()
}//注解: 【认真看】//没有 channel 的情况//打印结果混乱,person1 打印一个h,person2 打印一个 w,交叉了。不符合我们的要求//增加 channel ,则在
----------------------------------------- channel 实现同步和数据交互
fun main() {
ch := make(chan string)
defer fmt.Println("主协程也结束")
go func() {
defer fmt.Println("子协程调用完毕。")for i := 0; i < 2; i++{
fmt.Println("子协程 i=", i)
time.Sleep(time.Second)
}
ch
str :=
fmt.Println("str =", str)
}//注意:程序需求:主程序结束之前,能够完整执行匿名函数中的代码//使用 channel 配合完成
----------------------------------------- channel 无缓存&有缓存
c1 := make(chan int) 无缓冲
c2 := make(chan int,1) 有缓冲
c1< -1
//无缓冲:不仅仅是向 c1 通道放 1,//而是一直要等有别的协程
-----------------------------------------channel 单方向var ch1 chan int //ch1 是一个正常的 channle,不是单向的
var ch2 chan
var ch3
----------------------------------------- channel 应用
//此案例可以应用很多场景,每写一个,则可以消耗一个//此通道只能写,不能读
func producer(out chan
}
close(out)
}//此通道只能读,不能写
func consumer(in
fmt.Println("num =", num)
}
}
func main() {//创建一个双向通道
ch := make(chan int)//生产者,生产数字,写入 channel//开启一个协程
go producer(ch)//消费者,从channel读取内容打印
consumer(ch)
}
----------------------------------------- Timer
import ("time"
"fmt")
func main() {//创建一个定时器,设置时间为2s,2s后,往time通道写内容
timer := time.NewTimer(2 *time.Second)
fmt.Println("当前时间:", time.Now())//2s后,往timer.C写数据,有数据后读取
t :=
fmt.Println("t =", t)
}
----------------------------------------- select
//注解:go语言提供了一个关键字 select,通过 select 可以监听 channel 上的数据流动//语法:(类似 switch)
select{case
case chan
default://如果上面都没有成功,则进入default处理流程//注意:慎用,很消耗 cpu
}