网站首页 > 技术文章 正文
当程序中使用goroutine来操作一个全局变量时,拿map来举例,同时使用多个协程来向map中写入数据,此时代码可能会报错.
代码片段:
package main
import (
"fmt"
)
var (
result = make(map[int]int, 10)
)
func Strata(num int) {
res := 1
for i := 1; i <= num ; i ++ {
res *= i
}
// 将结果放入map中
result[num] = res
}
// 使用全局变量加锁方式 解决了 并发写入问题,但是 不知道具体 协程什么时候运行结束
// 那么这个问题怎么解决呢?
func main() {
// 这里开启多个协程, 完成这个任务
// 问题1: fatal error: concurrent map writes (存在并发安全问题)
// 问题2: 通过 go build -race main.go >> 拿到main.exe,并运行 >> Found 2 data race(s) 发现有两个存在竞争关系
for i := 1; i <= 20 ; i ++ {
go Strata(i)
}
// 输出结果
for i, v := range result {
fmt.Printf("result[%v]=%v \n", i, v)
}
}
报错信息:
fatal error: concurrent map writes
上面信息表示,当前map存在并发安全问题。
通过上面代码引出,有两种解决办法,一是使用golang提供的 sync包中的Mutex互斥锁来解决,在添加前后加锁。
另一种办法则是使用channel(管道)。channel是线程安全,多个协程操作同一管道时,不会发生资源竞争问题。 建议:使用channel时最好使用存放同一种数据类型。
Channel 基本操作
package main
import (
"fmt"
)
type Stu struct {
Name string
Age int
}
func main() {
// 定义一个管道
var newChan chan interface{}
newChan = make(chan interface{}, 10)
newChan <- "Mic"
newChan <- 10
// 添加一个Cat结构体
stu := Stu{"Tom", 20}
// 添加一个元素到newChan的channel中
newChan <- stu
// 如果想要取得最后一个元素,则先把前面的元素移除
<- newChan
<- newChan
newStu := <- newChan
// 打印newStu类型以及值
// 打印结果newStu=main.Stu, newStu={Tom 20}
fmt.Printf("newStu=%T, newStu=%v \n", newStu, newStu)
// 打印newStu的值
// 这样取直接报错: newStu.Name undefined (type interface{} has no field or method Name)
// 因为取出的是一个空接口, 表示没有Name这个属性。
//fmt.Println("newStu.Name=", newStu.Name)
// 解决上面的问题,需要使用到前面的说过的 类型断言
c := newStu.(Stu)
fmt.Println("c.Name=", c.Name) // 这样一来就不会报错了。
}
输出结果:
newStu=main.Stu, newStu={Tom 20}
c.Name= Tom
熟悉了Channel的基本使用, 则在使用协程操作时, 只需定义一个全局的管道,则就可以继续操作。
其他操作,后续继续学习。
- 上一篇: 并行编程语言:Go:Go语言并行编程最佳实践
- 下一篇: 一文搞懂pprof 一文搞懂伤寒论六经辨证
猜你喜欢
- 2024-10-12 漫画 | Linux 并发和竞态问题究竟是什么?
- 2024-10-12 【驱动】串口驱动分析(三)-serial driver
- 2024-10-12 synchronized锁 synchronized锁的是类还是对象
- 2024-10-12 Golang 程序遇到性能问题该怎么办?
- 2024-10-12 线程间通信——互斥锁 线程间互斥方式
- 2024-10-12 【Linux系统编程】互斥锁 linux 互斥锁优先级反转
- 2024-10-12 linux c/c++开发:多线程并发锁:互斥锁、自旋锁、原子操作、CAS
- 2024-10-12 每行代码都带注释,带你看懂Go互斥锁的源码
- 2024-10-12 一文搞懂pprof 一文搞懂伤寒论六经辨证
- 2024-10-12 并发原理系列八:信号量、互斥锁、自旋锁
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)