上篇:Go并发编程

简介: 上篇:Go并发编程
  1. 基本使用
package main
import (
 "fmt"
 "sync"
)
var wg sync.WaitGroup
func hello() {
 fmt.Println("hello func...")
 wg.Done() // 通知计数器减1
}
func main() {
 wg.Add(4) // 计数器,4个并发任务
 go hello()
 go hello()
 go hello()
 go hello()
 fmt.Println("main func!")
 wg.Wait() // 等待所有任务执行完成
}
  1. 改造一下,开启10000个goroutine
package main
import (
 "fmt"
 "sync"
)
var wg sync.WaitGroup
func hello(i int) {
 fmt.Println("hello func...", i)
 wg.Done()
}
func main() {
 // wg.Add(10000)
 for i := 0; i < 10000; i++ {
  wg.Add(1)
  go hello(i)
 }
 fmt.Println("main func!")
 wg.Wait()
}
  1. 将上一个例子改造成匿名函数
package main
import (
 "fmt"
 "sync"
)
var wg sync.WaitGroup
func main() {
 // wg.Add(10000)
 for i := 0; i < 10000; i++ {
  go func(i int) {
   fmt.Println("hello...", i)
  }(i)
 }
 fmt.Println("main func!")
 wg.Wait()
}
  1. 指定占用CPU核心数
package main
import (
 "fmt"
 "runtime"
 "sync"
)
var wg sync.WaitGroup
func test1() {
 for i := 0; i < 10; i++ {
  fmt.Println("func test1...", i)
 }
}
func test2() {
 for i := 0; i < 10; i++ {
  fmt.Println("func test2...", i)
 }
}
func main() {
 runtime.GOMAXPROCS(1) // 只占用1个CPU核心
 wg.Add(2)
 go test1()
 go test2()
 wg.Wait()
}
  1. 带缓冲区的通道,类似于异步的操作
package main
import "fmt"
func main() {
 ch1 := make(chan int, 1) // 只能存放1个值的缓冲区通道
 ch1 <- 10  // 发送
 x := <-ch1 // 接收
 fmt.Println(x)
 close(ch1)
}
  1. 无缓冲区的通道,又称为同步通道
package main
import "fmt"
func main() {
 ch1 := make(chan int) // 无缓冲区通道,又称为同步通道,
 ch1 <- 10             // 此时这里会处于阻塞的状态,除非有另外一个goroutine去取值,它才会发送
 x := <-ch1
 fmt.Println(x)
 close(ch1)
}
  1. 获取通道的容量和通道里的元素数量
package main
import "fmt"
func main() {
 ch1 := make(chan int, 10)
 ch1 <- 89
 ch1 <- 70
 fmt.Println(len(ch1)) // 获取通道中元素的数量
 fmt.Println(cap(ch1)) // 获取通道的容量
 close(ch1)
}
  1. 通道和goroutine的小栗子
package main
import (
 "fmt"
 "sync"
)
type myinterface interface{}
var ch1 = make(chan myinterface, 1)
var wg sync.WaitGroup
func sendData(i myinterface) {
 fmt.Printf("向通道发送 %v 成功\n", i)
 ch1 <- i
 wg.Done()
}
func readData() {
 v := <-ch1
 fmt.Println("从通道获取的值:", v)
 wg.Done()
}
func main() {
 nameArray := []string{"ttr", "tantianran"}
 wg.Add(2)
 go sendData(nameArray)
 go readData()
 wg.Wait()
}
  1. 通道+goroutine,实现协同干活例子2
package main
import "fmt"
func producer(ch chan int) {
 for i := 0; i < 10; i++ {
  ch <- i
 }
 close(ch)
}
func consumer(ch1 chan int, ch2 chan int) {
 for {
  v, ok := <-ch1
  if !ok {
   break
  }
  ch2 <- v * 2
 }
 close(ch2)
}
func main() {
 ch1 := make(chan int, 100)
 ch2 := make(chan int, 200)
 go producer(ch1)
 go consumer(ch1, ch2)
 for i := range ch2 {
  fmt.Println(i)
 }
}
相关文章
|
5月前
|
程序员 Go
Golang深入浅出之-Select语句在Go并发编程中的应用
【4月更文挑战第23天】Go语言中的`select`语句是并发编程的关键,用于协调多个通道的读写。它会阻塞直到某个通道操作可行,执行对应的代码块。常见问题包括忘记初始化通道、死锁和忽视`default`分支。要解决这些问题,需确保通道初始化、避免死锁并添加`default`分支以处理无数据可用的情况。理解并妥善处理这些问题能帮助编写更高效、健壮的并发程序。结合使用`context.Context`和定时器等工具,可提升`select`的灵活性和可控性。
90 2
|
2月前
|
缓存 NoSQL Go
通过 SingleFlight 模式学习 Go 并发编程
通过 SingleFlight 模式学习 Go 并发编程
|
4月前
|
Go
go语言并发编程(五) ——Context
go语言并发编程(五) ——Context
|
4月前
|
存储 缓存 Go
Go语言并发编程(三)——初窥管道
Go语言并发编程(三)——初窥管道
|
29天前
|
安全 大数据 Go
深入探索Go语言并发编程:Goroutines与Channels的实战应用
在当今高性能、高并发的应用需求下,Go语言以其独特的并发模型——Goroutines和Channels,成为了众多开发者眼中的璀璨明星。本文不仅阐述了Goroutines作为轻量级线程的优势,还深入剖析了Channels作为Goroutines间通信的桥梁,如何优雅地解决并发编程中的复杂问题。通过实战案例,我们将展示如何利用这些特性构建高效、可扩展的并发系统,同时探讨并发编程中常见的陷阱与最佳实践,为读者打开Go语言并发编程的广阔视野。
|
5月前
|
安全 Go 调度
Go语言中的并发编程
Go语言自带了强大的并发编程能力,它的协程机制可以让程序轻松地实现高并发。本文将从并发编程的基础概念出发,介绍Go语言中的协程机制、通道和锁等相关知识点,帮助读者更好地理解并发编程在Go语言中的实践应用。
|
2月前
|
存储 安全 Go
Go 并发编程精粹:掌握通道(channels)的艺术
Go 并发编程精粹:掌握通道(channels)的艺术
|
2月前
|
Go 开发者
使用Go语言进行高效并发编程
【8月更文挑战第9天】Go语言的并发模型以其简洁和高效著称,通过goroutines和channels,开发者可以轻松地编写出高性能的并发程序。此外,Go标准库还提供了丰富的并发原语和工具,如WaitGroup和Context,进一步简化了并发编程的复杂性。掌握Go语言的并发编程技巧,对于开发高性能、高并发的应用至关重要。希望本文能帮助你更好地理解和使用Go语言进行并发编程。
|
2月前
|
设计模式 安全 Go
深入探索 Go 语言中的并发编程
并发编程是现代软件开发中的重要组成部分,尤其是在多核处理器普及的今天,如何高效地利用硬件资源成为关键。Go 语言以其内置的并发支持而闻名,使得开发者能够轻松构建高性能、可扩展的应用程序。本文将深入探讨 Go 语言中的并发模型,涵盖 Goroutines、Channels 的使用,并讨论常见的并发陷阱及如何避免。
|
4月前
|
Go
如何在Go中进行文件操作以及如何使用协程来实现并发编程
如何在Go中进行文件操作以及如何使用协程来实现并发编程
45 2
下一篇
无影云桌面