前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go 语言并发编程初体验:简洁高效

Go 语言并发编程初体验:简洁高效

原创
作者头像
王二蛋
发布2024-05-07 18:07:59
810
发布2024-05-07 18:07:59

前言

Go语言是谷歌推出的一种的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。

谷歌软件工程师罗布派克(Rob Pike)说:

我们之所以开发Go,是因为过去10多年间软件开发的难度令人沮丧。和今天的C++或C一样,Go是一种系统语言,使用它可以进行快速开发。

以下是为什么开发Go的原因:

  • 计算机硬件技术更新频繁,性能提高很快。目前主流的编程语言发展明显落后于硬件,不能合理利用多核多CPU的优势提升软件系统性能。
  • 软件系统复杂度越来越高,维护成本越来越高,目前缺乏一个足够简洁高效的编程语言。
  • 企业运行维护很多c/c++的项目,c/c++程序运行速度虽然很快,但是编译速度确很慢,同时还存在内存泄漏的一系列的困扰需要解决。

GoLang 并发编程基本概念

进程与线程

进程定义:进程是并发执行的程序中分配和管理资源的基本单位。

线程定义:线程是进程的执行单元,是进行调度的实体,是比进程更小的独立运行单位。

线程和协程

协程是单线程下的并发,又称微线程、纤程。它是实现多任务的另一种方式,只不过是比线程更小的执行单元。

线程的切换是一个cpu在不同线程中来回切换,是从系统层面来,不止保存和恢复CPU上下文这么简单,会非常耗费性能。

而协程只是在同一个线程内来回切换不同的函数,只是简单的操作CPU的上下文,所以耗费的性能会大大减少。

并行与并发

并发定义:多线程交替操作同一资源类。

并行定义:多个线程同时操作多个资源类。

Erlang 之父 Joe Armstrong 用一张5岁小孩都能看懂的图解释了并发与并行的区别。

GoLang的协程机制

GoLang的协程机制(Goroutines),是一种非常强大的并发编程机制,它可以用来实现高效的并发操作,可轻松开启上万个协程。

占用内存远比 Java 、C 的线程少:

  • goroutine: 2KB
  • 线程:8MB

GoLang 并发实践

案例需求

统计1~2000000的数字中,哪些是素数。

传统方式实现

代码语言:go
复制
package main

import (
    "fmt"
    "math"
)

func isPrime(num int) bool {
    if num <= 1 {
        return false
    }
    for j := 2; j <= int(math.Floor(math.Sqrt(float64(num)))); j++ {
        if num%j == 0 {
            return false
        }
    }
    return true
}

func main() {
    num := 17 // 示例数字
    if isPrime(num) {
        fmt.Printf("数字 %d 是素数。\n", num)
    } else {
        fmt.Printf("数字 %d 不是素数。\n", num)
    }
}

isPrime函数接受一个整数num并返回一个布尔值,表示该数字是否为素数。在main函数中调用isPrime并打印出相应的结果。

使用 goroutines 实现并发

通过 goroutines 机制实现并发执行,提高执行效率。

直接通过 go 关键字就可以引入 goroutines 机制,实现并发操作,相比其他编程语言简化了很多。

代码语言:go
复制
package main

import (
    "fmt"
    "math"
)

var intChan chan int = make(chan int, 20000)

func main() {
    var primeChan chan int = make(chan int, 20000)
    var exitChan chan bool = make(chan bool, 8)

    go initChan(20000)

    for i := 0; i <= 8; i++ {
        go isPrimeA(intChan, primeChan, exitChan)
    }
    go func() { //0.839 seconds
        for i := 0; i <= 8; i++ {
            <-exitChan
        }
        close(primeChan)
    }()

    for {
        res, ok := <-primeChan
        if !ok {
            break
        }
        fmt.Println("素数:", res)
    }

}

func initChan(num int) {
    for i := 1; i <= num; i++ {
        intChan <- i
    }
    close(intChan)
}

func isPrimeA(intChan chan int, primeChan chan int) {
    for num := range intChan {
        if num <= 1 {
            continue
        }
        sqrtNum := int(math.Floor(math.Sqrt(float64(num))))
        isPrime := true
        for j := 2; j <= sqrtNum; j++ {
            if num%j == 0 {
                isPrime = false
                break
            }
        }
        if isPrime {
            primeChan <- num
        }
    }
}

func isPrime(num int) {
    for i := 1; i < num; i++ {
        var flag bool = true
        for j := 2; j < i; j++ {
            if i%j == 0 {
                flag = false
                continue
            }
        }
        if flag {
            fmt.Println("数字", i, "是素数。")
        }
    }
}

如果启动了多个 goroutine,它们之间如何通信?

goroutine 如何通信

在 Go 语言中,channel(通道) 用于在 goroutine 之间进行通信,类似于其他编程语言中的队列或管道。

goroutine 之间的通信不需要加锁,因为通道本身线程安全。

下面是 channel 的基本语法,可以对应上面的代码。

代码语言:go
复制
//使用 chan 关键字声明一个 channel。
var ch chan int
// 或者,在声明时直接初始化
ch := make(chan int)
//使用 <- 操作符将数据发送到 channel。
ch <- 42
//使用 <- 操作符从 channel 接收数据。
num := <-ch
// 关闭 channel:
close(ch)

channel 使用注意事项

1.声明之后需要make开辟内存才可以使用。

2.如果写满了,继续写会报错。

//fatal error: all goroutines are asleep - deadlock!

总结

通过GoLang的协程机制(Goroutines),可以看到Go语言确实足够简洁高效,也证实了:可以在不损失应用程序性能的情况下降低代码的复杂性。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • GoLang 并发编程基本概念
    • 进程与线程
      • 线程和协程
        • 并行与并发
          • GoLang的协程机制
          • GoLang 并发实践
            • 案例需求
              • 传统方式实现
                • 使用 goroutines 实现并发
                  • goroutine 如何通信
                    • channel 使用注意事项
                    • 总结
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                    http://www.vxiaotou.com