首页 > 其他分享 >《Go 语言并发之道》读书笔记(一)

《Go 语言并发之道》读书笔记(一)

时间:2022-11-11 15:36:04浏览次数:40  
标签:读书笔记 ++ goroutine value 并发 Go data

已经把《Go 语言并发之道》通读了一遍,非常不错的一本书,对于理解掌握Go语言的并发知识有很大的帮助,接下来我会把书中有用的知识通过代码示例出来,把一些比较好的知识点记录下来。
首先我们来看一段代码

var data int
go func() { data++ }()
if data == 0 {
	fmt.Println(" the value is 0.")
} else {
	fmt.Printf(" the value is %v.\n", data)
}

这段代码我们想把data + 1 后打印出来,但是结果打印出来的效果是 “the value is 0.”, 没有达到我们的预期,主要是因为调用 data++ 的这个goroutine没有先执行。 并发的难点就是控制程序执行的先后顺序。 那么我们能不能这样改进一下呢? 加一个sleep让主goroutine等待一下。

var data int
go func() { data++ }()
time.Sleep(1 * time.Second)
if data == 0 {
	fmt.Println(" the value is 0.")
} else {
	fmt.Printf(" the value is %v.\n", data)
}

打印出来的结果是 “the value is 1.”, 似乎达到了我们的预期, 但是实际是是不行的,也许data++方法里面还有耗时的操作,那程序运行的结果又有不确定性了。
这个程序还有个很大的问题, 两个goroutine共享了内存data, 如果这个data是只读的那还好,不会有什么影响,但是如果它是需要改变的,那么两个goroutine拿到的数据会存在不确定性。那么是否能够通过加锁来解决这个问题呢? 如下示例代码

	var memoryAccess sync.Mutex

	var data int
	go func() {
		memoryAccess.Lock()
		data++
		memoryAccess.Unlock()
	}()

	memoryAccess.Lock()

	if data == 0 {
		fmt.Println(" the value is 0.")
	} else {
		fmt.Printf(" the value is %v.\n", data)
	}
	memoryAccess.Unlock()

通过加锁我们能保证访问data的时候是独占的,但是它依然解决不了代码执行先后问题,而且看上去很不优雅。 既优雅又能解决问题的方法是下面的代码

	c := make(chan int)
	var data int

	go func() {
		data++
		c <- data
	}()

	data = <-c
	if data == 0 {
		fmt.Println(" the value is 0.")
	} else {
		fmt.Printf(" the value is %v.\n", data)
	}

输出结果“the value is 1.”
上面的代码定义了一个channel, 通过channel来传递value, 主goroutine遇到读取channel( <-c)的地方会等待,等待副goroutine把值填进去(c <- data), 其它部分的代码并发执行。
这里贴出书上Go语言并发性哲学总结: 追求简洁, 尽量使用channel, 并且认为goroutine的使用是没有成本的。
Go语言的座右铭: 使用通信来共享内存,而不是通过共享内存来通信

总结

这个例子虽然很简单,但是它能够引导我们进入Go语言并发的世界,让我们明白如何通过goroutine和channel来优雅的写出并发代码。 后续我们将列举出更多的示例,通过示例来说明一下知识。

标签:读书笔记,++,goroutine,value,并发,Go,data
From: https://www.cnblogs.com/dk168/p/16880596.html

相关文章

  • mongoDB大数据查询遇到的问题
    有一个30亿量级数据的库,如何全量爬取并分析?因为量级过大无法一次性爬取至本地再分析,考虑使用limit().skip()混合的方法,一次读取1万条数据进行分析存储,30亿数据分成30万份后......
  • 聊聊Go语言中的数组与切片
    1.数组数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。因为数组的长度是固定的,因此在Go语言中很少直接使用数组。和数组对应的类型是......
  • Django的简单使用
    Django基础简介基础简介1.软件框架一个公司是由公司中的各部部门来组成的,每一个部门拥有特定的职能,部门与部门之间通过相互的配合来完成让公司运转起来。一个软件框......
  • 【MongoDB】复制集 相关 (bully算法)
    复制集技术相比较传统的Master-Slave模式好处在于多了容错机制。所以MongoDB的复制集技术主要为用户解决了两大问题:第一就是primary节点挂了,其余的secondary节点会自动选举......
  • 【Go】协程
    今天主要学习了一下go语言的多线程,也写了一些例子,最开始还是很困惑。比如下面这个例子:packagemainimport"fmt"funcloop(){fori:=0;i<10;i++{fmt.Printf("......
  • Django APIView
    defget(self,request):print("================用户行为列表")dictionary_key=self.request.query_params.get('data_point_app_id')print('---------445-......
  • MixGo Max主控板使用Mixly最新版软件识别不到串口解决方法
    首先安装创客驱动文件,全部选择安装即可,安装之前请将杀毒软件关闭!创客驱动文件下载出现安装失败的驱动,说明已经安装过对应的驱动,点击确定即可。驱动安装完成后,......
  • django template 例子
    template不是django中的内容,而是在python中的。只是在django的松偶合的思想正好用到了这个东西。即写好界面的模板,然后再写好业务逻辑,最后组合即可,这样就将界面与逻辑分开来......
  • 【MongoDB】shard切分 原理
    1.角色:在一个MongoDB的shard集群中,会有三种角色:shard,config和routingshard:每一个shard节点都会包含数据集的一部分,是存储真正数据的节点;config:主要存储元数据或者配置信息,比......
  • django 配置静态文件
    在django中使用图片、css、或者js文件时,并不能直接使用,而要进行配置,也就是所谓的静态文件配置。1配置settings.py文件:STATIC_ROOT变量设置为空,不知道这个有什么用STATIC_URL......