golang 并发模型

Golang并发模型怎么使用

在Go语言中,并发是编程的核心概念之一,Go语言提供了多种并发模型,包括goroutine、channel、select语句等,本文将详细介绍Go语言的并发模型及其使用方法。

golang 并发模型

goroutine

goroutine是Go语言中最简单的并发模型,它是由Go语言运行时管理的轻量级线程,可以在一个程序中创建大量的goroutine来实现并发,创建一个goroutine非常简单,只需在函数调用前加上关键字go即可。

package main
import (
 "fmt"
 "time"
)
func printNumbers() {
 for i := 0; i < 10; i++ {
  time.Sleep(1 * time.Second)
  fmt.Printf("%d ", i)
 }
}
func printLetters() {
 for i := 'A'; i < 'A'+10; i++ {
  time.Sleep(1 * time.Second)
  fmt.Printf("%c ", i)
 }
}
func main() {
 go printNumbers() // 开启一个新的goroutine执行printNumbers函数
 go printLetters() // 开启一个新的goroutine执行printLetters函数
 time.Sleep(20 * time.Second) // 主线程等待20秒以确保所有子线程执行完毕
}

channel

channel是Go语言中用于在不同goroutine之间传递数据的通道,它可以看作是一个无界的队列,允许多个goroutine向其中发送数据,或从其中接收数据,channel的使用需要遵循一定的规则,如发送和接收操作必须在不同的goroutine中进行,以下是一个简单的channel使用示例:

golang 并发模型

package main
import (
 "fmt"
 "time"
)
func producer(ch chan int) {
 for i := 0; i < 10; i++ {
  ch <i // 将数据发送到channel中
  time.Sleep(1 * time.Second)
 }
 close(ch) // 关闭channel,表示没有更多的数据发送了
}
func consumer(ch chan int) {
 for data := range ch { // 从channel中接收数据
  fmt.Printf("%d ", data)
  time.Sleep(1 * time.Second)
 }
}
func main() {
 ch := make(chan int) // 创建一个channel
 go producer(ch) // 在一个新的goroutine中执行producer函数,并将channel传递给它
 go consumer(ch) // 在另一个新的goroutine中执行consumer函数,并将channel传递给它
 time.Sleep(20 * time.Second) // 主线程等待20秒以确保所有子线程执行完毕
}

select语句

select语句是Go语言中用于同时处理多个channel操作的一种机制,当有多个channel操作可发生时,select语句会随机选择其中一个操作执行,如果没有操作可发生,select语句会阻塞当前goroutine直到有操作可发生为止,以下是一个简单的select语句使用示例:

package main
import (
 "fmt"
 "time"
)
func printer(ch1 chan string, ch2 chan string) {
 for data := range ch1 { // 从ch1 channel接收数据并打印出来
  select { // 当ch2 channel中有数据可读时,从ch2 channel中读取数据并打印出来,否则继续等待ch2 channel中有数据可读的情况发生(阻塞当前goroutine)
  case msg := <-ch2: // 从ch2 channel中接收数据并打印出来(非阻塞)
  default: // 如果没有其他操作可发生,继续等待(阻塞当前goroutine)
   time.Sleep(500 * time.Millisecond) // 每隔500毫秒检查一次是否有其他操作可发生(避免过度占用CPU资源)
  }
  fmt.Println(data) // 打印接收到的数据(非阻塞)
 }
}

相关问题与解答

1、如何使用Go语言实现多任务调度?可以使用goroutine来实现多任务调度,每个goroutine代表一个独立的任务,通过控制goroutine的启动和停止,可以实现对任务的调度和管理,还可以使用time包中的Ticker和Timer来实现定时任务调度。

golang 并发模型

package main
import (
 \"fmt\"
 \"time\"
)
func main() {
 ticker := time.NewTicker(1 * time.Second)
 defer ticker.Stop()
 for {
  select {
  case <-ticker.C:
   // 每隔1秒钟执行一次任务
    fmt.Println("tick\")
  case <-time.After(5 * time.Second):
   // 当超过5秒钟后仍未收到ticker信号时,执行某个任务
    fmt.Println(\"timeout\")
   return
  }
 }
}

2、如何使用Go语言实现协程池?可以使用sync.WaitGroup来实现协程池,首先创建一个WaitGroup实例,然后在每次启动一个协程时将其加入到WaitGroup中,当协程执行完毕后,将其从WaitGroup中移除,最后在所有协程都执行完毕后调用WaitGroup的Wait方法等待所有协程结束。

package main
import (
 \"fmt\"
 \"sync\"
)
func worker(id int, done *bool) {
 defer func() {
  // 将已完成的任务从WaitGroup中移除
  done <true
 }()
 for {
  // 从队列中获取任务并执行
  task := getTaskFromQueue()
  if task == nil {
   // 没有任务可执行时退出循环
   break
  }
  // 执行任务
  doTask(task)
  // 所有任务都已完成,通知WaitGroup继续等待下一个任务
  <-done
 }
}
func main() {
 var waitGroup sync.WaitGroup // WaitGroup实例
gos_num := runtime.NumCPU()         // CPU核心数
nos_limit := gos_num + len(queue)*2       // 同时最多启动的协程数(包括主协程)
nos_limit = max(min(maxInt32, os_limit), minInt32)
semaphore := make(chan bool, os_limit)
done := make([]*bool, gos_num)
semaphore <true             // 将主协程加入到WaitGroup中
for i := range queue {
 semaphore <true           // 将工作协程加入到WaitGroup中
 go worker(i, &done[i])       // 在工作协程中执行worker函数
}
semaphore <true             // 将最后一个工作协程加入到WaitGroup中
waitGroup.Add(len(queue))
waitGroup.Wait()               // 所有工作协程都完成时等待它们结束
semaphore <true             // 将主协程从WaitGroup中移除并退出循环
memaphore <true             // 将最后一个工作协程从WaitGroup中移除并退出循环

原创文章,作者:K-seo,如若转载,请注明出处:https://www.kdun.cn/ask/316866.html

(0)
K-seoK-seoSEO优化员
上一篇 2024年2月16日 09:16
下一篇 2024年2月16日 09:18

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

免备案 高防CDN 无视CC/DDOS攻击 限时秒杀,10元即可体验  (专业解决各类攻击)>>点击进入