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

news2024/11/18 5:31:43

文章目录

  • 前言
  • GoLang 并发编程基本概念
    • 进程与线程
    • 线程和协程
    • 并行与并发
    • GoLang的协程机制
  • GoLang 并发实践
    • 案例需求
    • 传统方式实现
    • 使用 goroutines 实现并发
    • goroutine 如何通信
    • channel 使用注意事项
  • 总结

前言

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的数字中,哪些是素数。

传统方式实现

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 机制,实现并发操作,相比其他编程语言简化了很多。

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 的基本语法,可以对应上面的代码。

//使用 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语言确实足够简洁高效,也证实了:可以在不损失应用程序性能的情况下降低代码的复杂性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1662468.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

语义分割——脑肿瘤图像分割数据集

引言 亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 …

leetcode刷题——设计循环链表

题目要求我们设计循环队列&#xff0c;其特点是容量固定&#xff0c;队列循环&#xff0c;如图所示&#xff1a; 这里的队列我们以链表队列举例&#xff0c;对于循环&#xff0c;只需要把尾节点的指针指向头节点。重点是队列的容量固定&#xff1a;如何确定队列是否已满和空&am…

mamba-ssm安装卡着不动

项目中用到Mamba的小伙伴&#xff0c;causal_conv1d和 mamba-ssm两个包&#xff0c;但是会卡在Building wheel for mamba-ssm (setup.py) &#xff1a; 为了探究卡在了building的哪一步&#xff0c;加入–verbose进行显示&#xff1a; pip install mamba-ssm --no-cache-dir -…

[muduo网络库]——muduo库三大核心组件之 Poller/EpollPoller类(剖析muduo网络库核心部分、设计思想)

接着上文&#xff0c;[muduo网络库]——muduo库三大核心组件之Channel类&#xff08;剖析muduo网络库核心部分、设计思想&#xff09;&#xff0c;本章我们来学习muduo网络库中第二大核心组件Poller/EpollPoller类。 先回顾一下三大核心组件之间的关系。 接着我们进入正题。 P…

github删除自己的仓库

测试Github的时候新建了很多仓库&#xff0c;但是后来想删除&#xff0c;找了半天居然没有找到按钮。 我就推测这个删除的功能肯定藏起来了&#xff0c;后来度娘了一下&#xff0c;发现果然在一个比较隐蔽的位置&#xff0c;不知道以后这个功能会不会改到一个比较明显的位置吧…

flutter开发实战-log日志存储zip上传,发送钉钉机器人消息

flutter开发实战-log日志存储zip上传&#xff0c;发送钉钉机器人消息 当我们需要Apk上传的时候&#xff0c;我们需要将日志打包并上传到七牛&#xff0c;上传之后通过钉钉通知我们日志下载地址。 这里我使用的是loggy来处理日志 一、引入loggy日志格式插件 在工程的pubspec.…

Dijkstra求最短路 I:图解 详细代码(图解)

文章目录 题目&#xff1a;Dijkstra求最短路思路伪代码&#xff1a;代码优化优化代码&#xff1a;Java代码 总结 题目&#xff1a;Dijkstra求最短路 给定一个 n个点 m条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c;所有边权均为正值。 请你求出 1号点到 n号点的…

如何打开远程桌面连接?

远程桌面连接是一项强大的功能&#xff0c;它允许我们远程访问其他计算机&#xff0c;并在远程计算机上进行操作。这对于远程办公、技术支持和远程培训等场景非常有用。本文将介绍如何在不同操作系统中打开远程桌面连接。 Windows系统 在Windows操作系统中&#xff0c;打开远程…

实用的Chrome命令 帮你打开Chrome浏览器的隐藏功能

前言 Chrome作为主力浏览器&#xff0c;支持相当丰富的第三方扩展&#xff0c;其实浏览器本身也内置了大量实用的命令。许多实用的功能并没有直接显示在Chrome的菜单上。在这篇文章中&#xff0c;我们将介绍几个实用的chrome:// commands。 通过下面整理的 Chrome 命令&#x…

6.数据库

1.实体用矩形表示&#xff0c;属性用椭圆表示&#xff0c;联系用菱形表示 2.层次模型用数表示 3.网状模型用图结构表示 4.关系模型用二维表格结构来表示 5.概念模式基本表 外模式视图 内模式存储 6.模式/内模式映像 外模式/模式映像 7.数据的物理独立性 跟内模式关系 逻辑是视图…

C语言自定义类型枚举、枚举类型的定义、枚举的特点、以及自定义类型联合体、联合类型的定义、联合的特点、联合大小的计算、联合判断大小端 的介绍

文章目录 前言一、枚举1. 枚举类型的定义2. 枚举的特点 二、联合&#xff08;共用体&#xff09;1. 联合类型的定义2. 联合的特点3. 联合大小的计算4. 联合体判断大小端1. 不适用联合体判断大小端2. 使用联合体判断大小端 总结 前言 C语言自定义类型枚举、枚举类型的定义、枚举…

MyBatis——MyBatis入门程序

一、数据准备 二、开发步骤 1、引入依赖 <dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.15</version></dependency><dependency><groupId>c…

邻域注意力Transformer

邻域注意力&#xff08;NA&#xff09;&#xff0c;这是第一个高效且可扩展的视觉滑动窗口注意力机制&#xff0c;NA是一种逐像素操作&#xff0c;将自注意力&#xff08;SA&#xff09;定位到最近的相邻像素&#xff0c;因此与SA的二次复杂度相比&#xff0c;具有线性时间和空…

6 7 8 9 11 12 15 17 18 20 22cm散热风扇防护网风扇金属网罩

品牌&#xff1a;威驰 颜色分类&#xff1a;60mm/6cm金属网,80mm/8cm金属网,92mm/9.2cm金属网,110mm/11cm金属网,120mm/12cm金属网,150mm/15cm金属网,172mm/17.2cm金属网,200mm/20cm金属网,280mm/28cm金属网 1产品参数&#xff0c;防护网罩60 80 90 110 120 125 145 150 180…

详解:ic网站建设开发需要注意什么?

IC网站建设开发需注重专业内容的呈现、强大的产品检索功能、全面的技术支持、严格的合规性展示、便捷的采购工具、良好的用户账户管理、移动适应性和多语言支持&#xff0c;以及高性能与高安全性&#xff0c;以满足行业用户的专业需求&#xff0c;提升网站的实用性和吸引力。 …

linux - 搭建部署ftp服务器

ftp 服务: 实现ftp功能的一个服务,安装vsftpd软件搭建一台ftp服务器 ftp协议: 文件传输协议 (file transfer protocol),在不同的机器之间实现文件传输功能, 例如 视频文件下载,源代码文件下载 公司内部:弄一个专门的文件服务器,将公司里的文档资料和视频都存放…

游戏测试的基本要求

一.测试基本要求 1.研发开发游戏时&#xff1a;编写测试用例、提前开始测试独立模块、催促开发在规定工时完成内容 2.需求开发完成后&#xff1a;研发自测完成、我们执行测试用例、如果用例不完整&#xff08;时间够就维护用例&#xff09;、实际测试发现用例之外的问题 3.完…

DIY可视化软件环境准备

DIY官网可视化工具做好的可视化拖拽开发工具无须编程、零代码基础、所见即所得设计工具支持轻松在线可视化导出微信小程序、支付宝小程序、头条小程序、H5、WebApp、UNIAPP等源码 支持组件库,高颜值,卡片,列表,轮播图,导航栏,按钮,标签,表单,单选,复选,下拉选择,多层选择,级联选…

python中的数据可视化:二维直方图 hist2d()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 python中的数据可视化&#xff1a; 二维直方图 hist2d() 选择题 关于以下代码输出结果的说法中正确的是? import matplotlib.pyplot as plt import numpy as np x np.random.normal(0, 1, …

短剧奔向小程序,流量生意如何开启?

随着移动互联网的飞速发展&#xff0c;小程序作为一种轻量级、易传播的应用形态&#xff0c;逐渐在各个领域展现出其独特的商业价值。而最近爆火的短剧小视频作为一种受众广泛的娱乐形式&#xff0c;与小程序结合后&#xff0c;不仅为观众提供了更为便捷的观看体验&#xff0c;…