go channel 协程同步小例子

    科技2024-03-09  84

    目的

    程序完成有步骤依赖,时序关系,存储关系的需要阻塞-同步等待

    方法

    1 正常同步

    package main //练习协程goroutine之间的协同(同步),同步一定是降低效率的, //异步和并发才可以提升性能;但是流程上,许多依赖的接口和顺序执行, //储存的依赖关系,必须要同步和等待机制; import ( "fmt" "time" ) func routineWork(chFlag chan bool) { fmt.Println("Start working...") time.Sleep(time.Second * 3) fmt.Println("work done!") chFlag <- true } func main () { //设立一个flag,用于标记另一个协程完成了,以启动下一个程序 chanFlag := make(chan bool, 1) go routineWork(chanFlag) //同步等待chanFlag输出,相当于主程序阻塞挂起,等待子协程完成; //注销下面一行将会很有意思; 子协程没启动主程序就结束了; fmt.Println("finished: ",<- chanFlag) fmt.Println("如果没有打印工作日志,那么routine没有启动完,主程序就结束了。") //如果没有阻塞等待机制,除非主程序持续了足够的一段时间; //n=1 routinework只启动了一半;n>=3以上才能运行完 //const n = 1 //3 //time.Sleep(time.Second * n) }

    1 结果

    Start working… work done! finished: true 如果没有打印工作日志,那么routine没有启动完,主程序就结束了。

    正常同步上了,并且正常结束;

    2 阻塞操作<-chan注销

    package main //练习协程goroutine之间的协同(同步),同步一定是降低效率的, //异步和并发才可以提升性能;但是流程上,许多依赖的接口和顺序执行, //储存的依赖关系,必须要同步和等待机制; import ( "fmt" "time" ) func routineWork(chFlag chan bool) { fmt.Println("Start working...") time.Sleep(time.Second * 3) fmt.Println("work done!") chFlag <- true } func main () { //设立一个flag,用于标记另一个协程完成了,以启动下一个程序 chanFlag := make(chan bool, 1) go routineWork(chanFlag) //同步等待chanFlag输出,相当于主程序阻塞挂起,等待子协程完成; //注销下面一行将会很有意思; 子协程没启动主程序就结束了; //fmt.Println("finished: ",<- chanFlag) fmt.Println("如果没有打印工作日志,那么routine没有运行完,主程序就结束了。") //如果没有阻塞等待机制,除非主程序持续了足够的一段时间; //n=1 routinework只启动了一半;n>=3以上才能运行完 //const n = 1 //3 //time.Sleep(time.Second * n) }

    2 结果

    子协程没运行完,主程序就结束了。

    3 没有同步,但是主程序设置足够时间

    package main //练习协程goroutine之间的协同(同步),同步一定是降低效率的, //异步和并发才可以提升性能;但是流程上,许多依赖的接口和顺序执行, //储存的依赖关系,必须要同步和等待机制; import ( "fmt" "time" ) func routineWork(chFlag chan bool) { fmt.Println("Start working...") time.Sleep(time.Second * 3) fmt.Println("work done!") chFlag <- true } func main () { //设立一个flag,用于标记另一个协程完成了,以启动下一个程序 chanFlag := make(chan bool, 1) go routineWork(chanFlag) //同步等待chanFlag输出,相当于主程序阻塞挂起,等待子协程完成; //注销下面一行将会很有意思; 子协程没启动主程序就结束了; //fmt.Println("finished: ",<- chanFlag) fmt.Println("如果没有打印工作日志,那么routine没有运行完,主程序就结束了。") //如果没有阻塞等待机制,除非主程序持续了足够的一段时间; //n=1 routinework只启动了一半;n>=3以上才能运行完 const n = 1 //3 time.Sleep(time.Second * n) }

    3 结果

    const n = 1 Start working… 如果没有打印工作日志,那么routine没有运行完,主程序就结束了。

    const n = 3 如果没有打印工作日志,那么routine没有运行完,主程序就结束了。 Start working… work done!

    延迟3s以上,子协程便能运行完毕了;

    同时注意到,协程的第一个打印和主程序的print有先有后,并发运行,哪一个先运行完不定的。—实际是背后的CPU调度进程的不确定性。

    Processed: 0.020, SQL: 8