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

Like (0)
Donate 微信扫一扫 微信扫一扫
K-seo的头像K-seoSEO优化员
Previous 2024-02-16 09:16
Next 2024-02-16 09:18

相关推荐

  • python创建线程的方法

    Python创建线程的方法有很多,其中最常用的是使用threading模块。threading模块提供了一个简单的方法来创建和管理线程,下面我们详细介绍如何使用threading模块创建线程。1. 导入threading模块在开始创建线程之前,我们需要先导入threading模块,通常情况下,我们只需要导入threading模块即可。……

    2024-01-11
    0196
  • C#中manualresetevent的用法有哪些

    在C中,ManualResetEvent是一个同步原语,用于线程间的通信,它允许一个或多个等待的线程继续执行,一旦某个特定的条件得到满足,这个类是System.Threading命名空间的一部分。ManualResetEvent的基本用法ManualResetEvent可以通过两种状态来理解:set和unset,当ManualRese……

    2024-02-01
    0164
  • linux如何查看系统线程数量

    在Linux系统中,有多种方法可以查看系统线程数量,这些方法包括但不限于使用命令行工具、读取特定的系统文件或利用系统监控工具,以下是一些常用的方法来查看Linux系统的线程数量:1、使用ps命令ps命令是Linux中用于报告当前进程状态的标准工具,通过结合适当的选项,我们可以使用它来显示系统中的线程信息。ps -eo nlwp | a……

    2024-02-11
    0427
  • java线程调度算法是什么意思

    Java线程调度算法是什么?在Java中,线程调度是操作系统自动完成的,Java也提供了一些内置的同步原语,如ReentrantLock、Semaphore等,来帮助开发者更好地控制线程的执行顺序,本文将详细介绍Java线程调度算法的相关知识。1、线程状态在Java中,线程有6种状态,分别是:新建(New)、就绪(Runnable)、……

    2024-01-24
    0204
  • java让线程停止执行的方法

    Java中如何将线程停止又开始?在Java中,我们可以使用多种方法来停止和重新启动一个线程,下面我将介绍几种常见的方法。1、使用标志位控制线程的停止和启动这种方法的基本思想是使用一个布尔类型的变量作为标志位,当该变量为true时表示线程需要继续执行,为false时表示线程需要停止,在线程的循环体内,我们可以检查这个标志位,如果它为tr……

    2024-01-29
    0176
  • 电脑i9和i7有什么区别

    电脑处理器是计算机的核心部件之一,它负责执行计算机程序中的指令,在众多处理器中,Intel的i9和i7是最受欢迎的两款高端处理器,如何选择适合自己的处理器呢?本文将从性能、价格、功耗和适用场景等方面进行分析,帮助大家了解i9和i7的区别,从而做出明智的选择。一、性能对比i9和i7的主要区别在于核心数量、线程数量和主频,i9通常拥有更多……

    2023-12-10
    0209

发表回复

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

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