c语言编程笔录

首页 >   > 笔记大全

笔记大全

golang实现并行

更新时间:2023-07-09

golang实现并行

Go语言是一门并发支持的语言,可以通过goroutine来实现并行编程,下面会详细介绍goroutine的使用。

1. goroutine介绍

goroutine是乔治语言中的一个轻量级线程,它在Go的运行时环境中被执行。与传统的线程相比,goroutine被称为轻量级线程,因为它们的创建和销毁操作的开销很小。在Go中,可以通过关键字“go”来创建一个goroutine,并在其中执行函数。下面是一个示例:

      package main

      import "fmt"

      func f(from string) {
        for i :=0; i < 5; i++ {
          fmt.Println(from, ":", i)
        }
      }

      func main() {
        // 创建并运行goroutine
        go f("goroutine")

        // 在主线程中执行函数
        f("main")

        // 等待输入,防止程序过早退出
        var input string
        fmt.Scanln(&input)
      }
    

在上面的示例中,我们创建了一个函数f,并在main函数中使用关键字“go”创建了一个goroutine,并在其中执行了函数f。主线程中也执行了函数f。可以看到,主线程和goroutine同时执行,输出结果会交替出现。

2. 并发安全

在并发编程中,一个很常见的问题就是竞态条件。竞态条件发生在多个goroutine竞争同一资源时。为了解决这个问题,Go提供了一个叫做mutex的互斥锁。下面是一个示例:

      package main

      import (
        "fmt"
        "sync"
        "time"
      )

      // 共享资源
      var counter int

      func increment(wg *sync.WaitGroup, m *sync.Mutex) {
        m.Lock()
        counter++
        m.Unlock()
        wg.Done()
      }

      func main() {
        // 创建互斥锁
        var mutex sync.Mutex

        // 创建等待组
        var wg sync.WaitGroup

        // 启动10个goroutine增加counter的值
        for i :=0; i < 10; i++ {
          wg.Add(1)
          go increment(&wg, &mutex)
        }

        // 等待所有goroutine执行完毕
        wg.Wait()

        // 打印counter的值
        fmt.Println("Counter:", counter)
      }
    

在上面的示例中,我们创建了一个互斥锁mutex,并在increment函数中使用它来保护共享资源counter。我们创建了10个goroutine来并行增加counter的值。通过使用互斥锁,我们可以保证counter的值不会被多个goroutine同时访问。

3. 通道

在Go语言中,可以使用通道(channel)来协调goroutine之间的交互。通道充当了同步器的角色,在goroutine之间传递数据并同步它们的执行。下面是一个简单的示例:

      package main

      import (
        "fmt"
      )

      func main() {
        // 创建通道
        ch :=make(chan int)

        // 启动goroutine
        go func() {
          ch <- 1
        }()

        // 从通道中读取数据
        fmt.Println(<-ch)
      }
    

在上面的示例中,我们创建了一个通道ch,并在一个匿名goroutine中将数字1发送到通道中。在main函数中,我们使用<-运算符从通道中读取数据,并将其打印到标准输出中。可以看到,通道充当了goroutine之间传递数据的媒介,并保证了它们的执行顺序。

4. 常见的并发模式

在Go语言中,有许多用于并发编程的常见模式。下面是其中的一些:

  • Worker pool pattern:使用一组goroutine处理一组输入任务。
  • Pipeline pattern:将输入与输出通道连接起来,形成一条管道。
  • Producer-consumer pattern:使用多个goroutine来生产和消费数据。
  • Pub-sub pattern:使用多个订阅者和发布者来实现消息传递。

这些模式都是由goroutine和通道构建的,可以帮助我们更好地利用并发性。