Go并发编程

一、goroutine 和 通道

在Go语言中,每一个并发执行的活动成为goroutine。通道则是每一个goroutine之间传递消息的工具。

1、Goroutine

在一个Go程序中,只有一个主Goroutine来调用main函数。生成新的goroutine也十分简单,例如有一个函数:f(), 只需在其前面加上go关键字即可将其作为并发程序执行。
例:

package mainimport ("fmt""time"
)func main() {n := 5//开启goroutinego f(n)for i := 0; i < n; i++ {fmt.Println("I am goroutine main()")time.Sleep(50 * time.Millisecond)}
}func f(n int) {for i := 0; i < n; i++ {fmt.Println("I am goroutine f()")time.Sleep(50 * time.Millisecond)}
}// sout:
// I am goroutine main()
// I am goroutine f()
// I am goroutine f()
// I am goroutine main()
// I am goroutine main()
// I am goroutine f()
// I am goroutine f()
// I am goroutine main()
// I am goroutine main()
// I am goroutine f()

虽然Go语言实现并发十分方便,但是如何实现goroutine之间的通信以及保证并发的安全性依然是一件有挑战的事。

2、通道(chan)

通道是goroutine之间的连接,让特定的值在各个goroutine之间传递。
使用make函数创建一个通道:ch := make(chan type, cap). type为ch传递值的类型,cap为通道的大小(同时能容纳多少值),type可以为任意类型。
通道对应操作(都存在阻塞):

  1. 发送 ( c h < − x ch<-x ch<x) x为对应类型的变量,ch为通道。(ch满了会存在阻塞)
  2. 接受( x < − c h x<-ch x<ch)x为对应类型的变量,ch为通道。(ch空了会存在阻塞)
  3. 关闭通道close(ch)(ch发送操作被禁止,接受操作被释放)

无缓冲通道: 通道只有一个元素,接受方和发送方会相互阻塞。
管道: 通道有多个chan元素,用来连接不同的goroutine,一个chan的输入是另一个chan的输入。
单向通道类型: 类型( c h a n < − i n t chan<-int chan<int)为只能发送的通道,类型( < − c h a n i n t <-chan int <chanint)为只能接收的int类型通道。
缓冲通道: 有一个元素队列,一个cap大于1的通道类型。

注意细节:

  1. chan变量默认值为nil,使用’=='时若二者是同一通道数据的引用时返回true。
  2. 若关闭后还有写操作会发生宕机panic,读取其零值故可将其作为开关使用。
  3. 操作 x,ok := <-ch (x为读取的值,ok为bool值,当ch被close时会返回false,故可以使用range来获取ch的值直到ch被close)。
  4. select开关操作(关闭某一服务),利用select捕获通道关闭的信息,从而关闭对应的服务。
    例:
	done := make(chan struct{})go func() {os.Stdin.Read(make([]byte, 1))close(done)}()loop:for {select {//捕获是否关闭。case <-done:fmt.Println("program end!")break loopdefault:fmt.Println("program runing!")}time.Sleep(1 * time.Second)}

一个爬虫案例,使用bfs方式爬取一个网页的所有url:

package gorunimport ("fmt""log""net/http""golang.org/x/net/html"
)func Catch() {//通道用来在goroutine之间传递结果worklist := make(chan []string)//计数器用来判断结束状态,关闭goroutinecnt := 0go func() {worklist <- []string{"http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/person/person_home.html"}}()cnt++//标记已遍历的url,防止重复的url被读取seen := make(map[string]bool)for ; cnt > 0; cnt-- {list := <-worklistfor _, link := range list {if !seen[link] {seen[link] = truecnt++//慢函数,用新的goroutine执行,提高效率。go func(link string) {//该处会不停地生成新的goroutineworklist <- crawl(link)}(link)}}}
}
//chan变量,利用其阻塞的特性,用于控制新增goroutine的数量
var token = make(chan struct{}, 20)// 在生成goroutine时做限制,控制生成的goroutine的数量
func crawl(url string) []string {fmt.Println(url)//获取token <- struct{}{}list, err := extract(url)//释放defer func() {<-token}()if err != nil {log.Println(err)}return list
}//分析网页中的html文件,搜索其中的url
func extract(url string) ([]string, error) {resp, err := http.Get(url)if err != nil {return nil, err}if resp.StatusCode != http.StatusOK {resp.Body.Close()return nil, fmt.Errorf("getting %s: %s", url, resp.Status)}doc, err := html.Parse(resp.Body)resp.Body.Close()if err != nil {return nil, fmt.Errorf("parse %s as html: %v", url, err)}var links []stringvisitNode := func(n *html.Node) {if n.Type == html.ElementNode && n.Data == "a" {for _, a := range n.Attr {if a.Key != "href" {continue}link, err := resp.Request.URL.Parse(a.Val)if err != nil {continue}links = append(links, link.String())}}}forEachNode(doc, visitNode, nil)return links, nil
}func forEachNode(n *html.Node, pre, post func(n *html.Node)) {if pre != nil {pre(n)}for c := n.FirstChild; c != nil; c = c.NextSibling {forEachNode(c, pre, post)}if post != nil {post(n)}
}

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

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

相关文章

GZ035 5G组网与运维赛题第9套

2023年全国职业院校技能大赛 GZ035 5G组网与运维赛项&#xff08;高职组&#xff09; 赛题第9套 一、竞赛须知 1.竞赛内容分布 竞赛模块1--5G公共网络规划部署与开通&#xff08;35分&#xff09; 子任务1&#xff1a;5G公共网络部署与调试&#xff08;15分&#xff09; 子…

springboot actuator jvm监控丢失

1、背景 系统接入了监控prometheus和grafana&#xff0c;某天grafana突然发现只有几台机器可以看到指标。 随便点击一个地址http://192.168.0.76:8681/lms/actuator/prometheus访问指标&#xff0c;发现JVM相关指标全部丢失 2、解决方法 从网上查找相关资料&#xff0c;逐一…

【实践篇】一次Paas化热部署实践分享 | 京东云技术团队

前言 本文是早些年&#xff0c;Paas化刚刚提出不久时&#xff0c;基于部门内第一次Paas化热部署落地经验所写&#xff0c;主要内容是如何构建一些热部署代码以及一些避雷经验。 一、设计-领域模型设计 1.首先&#xff0c;确定领域服务所属的领域 2.其次&#xff0c;确定垂直…

leetcode经典面试150题---6.旋转数组

题目描述 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数 示例 1&#xff1a; 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步…

2024上海国际合成生物学与绿色生物制造展览会8月7-9号上海举办

2024年8月7日至9日&#xff0c;一场生物制造领域的盛会将在上海新国际博览中心闪亮登场。那就是2024上海国际合成生物学与绿色生物制造展览会。这场盛会将同期举办2024第13届上海国际生物发酵展&#xff0c;形成了一个强大的“生物军团”&#xff0c;展现出生物科技领域的无限魅…

图解系列--理解L3交换机的性能与功能

04.01 何为 L3 交换机 L3交换机是一种在L2 交换机的基础上增加了路由选择功能的网络硬件&#xff0c;能够通过基于ASIC 和 FPGA 的硬件处理高速实现网络功能和转发分组。L2 是指 OSI 参考模型中的L2, 也就是数据链路层。L2 交换机能够基于该层主要编址的 MAC 地址&#xff0c;…

深度学习框架TensorFlow.NET环境搭建1(C#)

测试环境 visual studio 2017 window10 64位 测试步骤如下&#xff1a; 1 新建.net framework控制台项目&#xff0c;工程名称为TensorFlowNetDemo&#xff0c;.net framework的版本选4.7.2&#xff0c;如下图&#xff1a; 2 分别安装TensorFlow.NET包(先装)和SciSharp.…

力扣每日一题100:相同的树

题目描述&#xff1a; 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 示例 1&#xff1a; 输入&#xff1a;p [1,2,3], q [1,2,3] 输出&…

计算机毕设 基于大数据的抖音短视频数据分析与可视化 - python 大数据 可视化

文章目录 0 前言1 课题背景2 数据清洗3 数据可视化地区-用户观看时间分界线每周观看观看路径发布地点视频时长整体点赞、完播 4 进阶分析相关性分析留存率 5 深度分析客户价值判断 5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;…

ThreadLocal用法

ThreadLocal 用法 ThreadLocal从字面意思来说&#xff0c;独立线程空间的意思&#xff0c;所以其用法也很简单&#xff0c;就是当一个线程需要有自己的变量&#xff0c;并且这个变量不想和其他变量共享&#xff0c;那么就使用ThreadLocal 变量&#xff1a; 比如常见的我们经常…

解决一个Qt程序崩溃的问题

当Qt崩溃时&#xff0c;使用Qt Creator调试&#xff0c;也无法定位到是哪个地方除了问题。只发现日志报出一个Fatal。 Fatal: 2023-11-05 00:16:26 [io\qprocess_win.cpp:826] ASSERT: "pid" in file io\qprocess_win.cpp, line 826触发的情况&#xff0c;就是使用…

VR全景技术在文化展示与传播中有哪些应用?

引言&#xff1a; 随着科技的不断进步&#xff0c;虚拟现实&#xff08;VR&#xff09;全景技术已经成为文化展示与传播领域的一项重要工具。那么VR全景技术是如何改变文化展示与传播方式&#xff0c;VR全景技术又如何推动文化的传承和普及呢&#xff1f; 一&#xff0e;VR技术…

壹[1],Opencv常用结构

1&#xff0c;Point类&#xff1a;点表示 point表示二维结构的点,(x,y) cv::Point point; point.x 100; point.y 100; 2&#xff0c;Scalar类&#xff1a;颜色表示 cv::Scalar colorBlue(255,0,0);//蓝色 cv::Scalar colorGreen(0, 255, 0);//绿色 cv::Scalar colorRed(0, …

第11章_数据处理之增删改

文章目录 1 插入数据1.1 实际问题1.2 方式 1&#xff1a;VALUES的方式添加1.3 方式2&#xff1a;将查询结果插入到表中演示代码 2 更新数据演示代码 3 删除数据演示代码 4 MySQL8新特性&#xff1a;计算列演示代码 5 综合案例课后练习 1 插入数据 1.1 实际问题 解决方式&#…

英语语音识别,语言评测,语音打分实践与代码实现

项目在这&#xff1a;couldn/speech-evaluation-of-english 详细的可查看项目内的md文档

是时候放弃 Java 序列化了

基本概念 Java 序列化和反序列化三连问&#xff1a; 什么是 Java 序列化和反序列化&#xff1f;为什么需要 Java 序列化和反序列化&#xff1f;如何实现 Java 序列化和反序列化&#xff1f; 是什么 一句话就能够说明白什么是 Java 序列化和反序列化&#xff1f;Java 序列化…

linux傻瓜式安装Java环境及中间件

linux配置Java环境及中间件 1.傻瓜式安装Java1.下载2.追加3.刷新测试 2.傻瓜式安装docker1.docker卸载2.docker安装 3.Docker傻瓜式安装Redis1.傻瓜式安装安装并配置 4.Docker傻瓜式安装RabbitMQ5.Docker傻瓜式安装MySql1.拉取2.配置 6.傻瓜式安装Nacos1.官网下载nacos2.SQL文件…

vue2.0 打包,nginx部署

1、修改这里为空 否则报错&#xff1a;vue is undefined 2、修改为hash&#xff0c;重点&#xff1a;打包dist文件运行&#xff0c;必须这样 3、安装ngnix&#xff0c;重点&#xff1a;使用node的包&#xff1a;httpserve&#xff0c;失败 4、重点&#xff1a;配置代理转发 前端…

MySQL:事务

目录 概念事务特性开始事务事务的状态事务并发问题事务隔离级别 概念 MySQL事务是一组在数据库中执行的操作&#xff0c;它们必须要么全部成功执行&#xff0c;要么全部不执行。MySQL事务被设计为确保数据库中的数据的完整性和一致性&#xff0c;即使在并发访问的情况下也是如…

MySQL进阶之性能优化与调优技巧

数据库开发-MySQL 1. 多表查询1.1 概述1.1.2 介绍1.1.3 分类 1.2 内连接1.3 外连接1.4 子查询1.4.1 介绍1.4.2 标量子查询1.4.3 列子查询1.4.4 行子查询1.4.5 表子查询 2. 事务2.1 介绍2.2 操作2.3 四大特性 3. 索引3.1 介绍3.2 结构3.3 语法 1. 多表查询 1.1 概述 1.1.2 介绍…