9.并发
来源:互联网 发布:手机玩gta5的软件 编辑:程序博客网 时间:2024/06/06 14:28
1.并发
2.goroutine
package mainimport ( "fmt" "runtime" "sync")func main() { // 分配一个逻辑处理器给调度器使用 runtime.GOMAXPROCS(1) // wg 用来等待程序完成 // 计数加 2,表示要等待两个goroutine //WaitGroup 是一个计数信号量,可以用来记录并维护运行的goroutine。如果WaitGroup //的值大于0,Wait 方法就会阻塞 var wg sync.WaitGroup wg.Add(2) fmt.Println("Start Goroutines") // 声明一个匿名函数,并创建一个goroutine go func() { // 在函数退出时调用Done 来通知main 函数工作已经完成 defer wg.Done() for count := 0; count < 3; count++ { for char := 'a'; char < 'a' + 26; char++ { fmt.Printf(" %c ",char) } } }() go func() { defer wg.Done() for count := 0; count < 3; count++ { for char := 'A'; char < 'A' + 26; char++ { fmt.Printf(" %c ",char) } } }() // 等待 goroutine 结束 fmt.Println("Waiting To Finish") wg.Wait() fmt.Println("\nTetmination Programing")}
go build -race 程序名 // 调试并发
3.锁住共享资源
package mainimport ( "fmt" "runtime" "sync" "sync/atomic")var ( conter int64 // counter 是所有goroutine 都要增加其值的变量 wg sync.WaitGroup // wg 用来等待程序结束)func main() { // 计数加 2,表示要等待两个goroutine wg.Add(2) // 计数加 2,表示要等待两个goroutine go incCounter(1) go incCounter(2) // 等待 goroutine 结束 wg.Wait() fmt.Println("Final Counter : ",conter)}// incCounter 增加包里counter 变量的值func incCounter(id int) { // 在函数退出时调用Done 来通知main 函数工作已经完成 defer wg.Done() for count := 0; count < 2; count++ { // 在函数退出时调用Done 来通知main 函数工作已经完成 atomic.AddInt64(&conter,1) // 当前 goroutine 从线程退出,并放回到队列 runtime.Gosched() }}
package mainimport ( "fmt" "sync" "sync/atomic" "time")var ( shutdown int64 wg sync.WaitGroup)func main() { wg.Add(2) go doWork("A") go doWork("B") time.Sleep(1 * time.Second) fmt.Println("Shutdown Now") // 该停止工作了,安全地设置shutdown 标志 atomic.StoreInt64(&shutdown,1) wg.Wait()}func doWork(name string) { defer wg.Done() for { fmt.Printf("Doing %s Work\n",name) time.Sleep(250 * time.Millisecond) // 检测之前的shutdown 标志来决定是否提前终止 // 要停止工作了吗? if atomic.LoadInt64(&shutdown) == 1 { fmt.Printf("Shutting %s Down\n",name) break } }}
4.互斥锁
package mainimport ( "fmt" "runtime" "sync")var ( counter int wg sync.WaitGroup mutex sync.Mutex)func main() { wg.Add(2) go incCounter(1) go incCounter(2) wg.Wait() fmt.Printf("Final Counter : %d\n",counter)}// incCounter 使用互斥锁来同步并保证安全访问func incCounter(id int) { // 在函数退出时调用Done 来通知main 函数工作已经完成 defer wg.Done() // 同一时刻只允许一个goroutine 进入 // 这个临界区 for count := 0; count < 2; count++ { mutex.Lock() { // 捕获 counter 的值 value := counter // 当前 goroutine 从线程退出,并放回到队列 runtime.Gosched() // 增加本地 value 变量的值 value++ // 将该值保存回counter counter = value } // 释放锁,允许其他正在等待的goroutine mutex.Unlock() }}
5.通道
package mainimport ( "fmt")func main() { // 有缓冲的字符串通道,包含一个10 个值的缓冲区 buffer := make(chan string, 10) // 通过通道发送一个字符串 buffer <- "Goper" // 从通道接收一个字符串 value := <-buffer fmt.Println(value)}
无缓冲的通道:
package mainimport ( "fmt" "math/rand" "sync" "time")// wg 用来等待程序结束var wg sync.WaitGroupfunc init() { rand.Seed(time.Now().UnixNano())}func main() { // 创建一个无缓冲的通道 court := make(chan int) // 计数加 2,表示要等待两个goroutine wg.Add(2) // 启动两个选手 go palyer("Nadal",court) go palyer("Djokovic",court) // 发球 court <- 1 // 等待游戏结束 wg.Wait()}// player 模拟一个选手在打网球func palyer(name string,court chan int) { // 在函数退出时调用Done 来通知main 函数工作已经完成 defer wg.Done() for { // 等待球被击打过来 ball, ok := <- court if !ok { // 等待球被击打过来 fmt.Printf("Player %s Won\n",name) return } // 选随机数,然后用这个数来判断我们是否丢球 n := rand.Intn(100) if n%13 == 0 { fmt.Printf("Player %s Missed\n",name) // 关闭通道,表示我们输了 close(court) return } // 显示击球数,并将击球数加1 fmt.Printf("Player %s Hit %d \n",name,ball) ball++ // 将球打向对手 court <- ball }}
package mainimport ( "fmt" "sync" "time")var wg sync.WaitGroupfunc main() { // 创建一个无缓冲的通道 baton := make(chan int) // 为最后一位跑步者将计数加1 wg.Add(1) // 第一位跑步者持有接力棒 go Runner(baton) // 开始比赛 baton <- 1 // 等待比赛结束 wg.Wait()}// Runner 模拟接力比赛中的一位跑步者func Runner(baton chan int) { var newRunner int // 等待接力棒 runner := <- baton // 开始绕着跑道跑步 fmt.Printf("Runner %d Running with Baton \n",runner) // 创建下一位跑步者 if runner != 4 { newRunner = runner + 1 fmt.Printf("Runner %d to the lien\n",newRunner) go Runner(baton) } // 围绕跑道跑 time.Sleep(100 * time.Millisecond) // 比赛结束了吗? if runner == 4 { fmt.Printf("Runner %d Finish \n",runner) wg.Done() return } // 将接力棒交给下一位跑步者 fmt.Printf("Runner %d Exchange With Runner %d\n", runner, newRunner) baton <- newRunner}
有缓冲的通道:
package mainimport ( "fmt" "math/rand" "sync" "time")const ( // 要使用的goroutine 的数量 numberGoroutens = 4 // 要处理的工作的数量 taskLoad = 10)// wg 用来等待程序完成var wg sync.WaitGroup// init 初始化包,Go 语言运行时会在其他代码执行之前,优先执行这个函数func init() { // 初始化随机数种子 rand.Seed(time.Now().Unix())}func main() { // 创建一个有缓冲的通道来管理工作 tasks := make(chan string,taskLoad) // 启动 goroutine 来处理工作 wg.Add(numberGoroutens) for gr := 1; gr <= numberGoroutens; gr++ { go worker(tasks, gr) } // 增加一组要完成的工作 for post := 1; post <= taskLoad; post++ { tasks <- fmt.Sprintf("Task : %d",post) } // 当所有工作都处理完时关闭通道,以便所有goroutine 退出 close(tasks) // 等待所有工作完成 wg.Wait()}//worker 作为goroutine 启动来处理,从有缓冲的通道传入的工作func worker(tasks chan string,worker int) { // 通知函数已经返回 defer wg.Done() for { // 等待分配工作 task, ok := <- tasks if !ok { // 这意味着通道已经空了,并且已被关闭 fmt.Printf("Worker : %d : Shutting down \n",worker) return } // 显示我们开始工作了 fmt.Printf("Worker :%d : Startig %s\n",worker,task) // 随机等一段时间来模拟工作 sleep := rand.Int63n(100) time.Sleep(time.Duration(sleep)*time.Millisecond) // 显示我们完成了工作 fmt.Printf("Worker : %d : Complete %s \n",worker,task) }}
阅读全文
0 0
- 9.并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 并发
- 获取模型线圆的中心
- 解决select2在bootstrap模态框中下拉框隐藏的问题
- nginx服务三---nginx配置文件解释补充
- iOS开发-OC 中给 nil 发送消息会崩溃吗?为什么?
- 高仿微信通讯录列表
- 9.并发
- 蓝桥杯 算法训练 最小乘积(基本型)
- springBoot+Jpa(hibernate)数据库基本操作
- 【Spring】整合JDBC连接数据库
- elasticsearch详解(三)——elasticsearch配置安装
- centos7安装VirtualBox
- 交叉验证(Cross Validation)
- 【OpenCV】Hough检测
- postgresql 10 Background Writer