目的
程序完成有步骤依赖,时序关系,存储关系的需要阻塞-同步等待
方法
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调度进程的不确定性。

本文通过三个示例探讨了Go语言中协程的同步机制。正常同步确保了协程间的顺序执行,通过channel等待子协程完成。取消同步会导致主程序提前结束,而设置足够长的延迟时间可以允许子协程完成,但并不保证顺序。重点讨论了同步在并发执行中的必要性和影响效率的因素。
1352

被折叠的 条评论
为什么被折叠?



