Map 集合是 Go 中提供的一个 KV 结构的数据类型,对它的操作在实际的开发中应该是非常多的,不过它不是一个线程安全的。

1 、Map 不是线程安全的

编写下面的测试代码:

func TestUnsafeMap(t *testing.T) {
// 创建一个线程不安全的map
myMap := make(map[int]int) // 创建一个WaitGroup用于等待所有goroutine完成
var wg sync.WaitGroup // 启动多个goroutine并发访问map
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
myMap[i] = i * 10 // 向map中写入数据
fmt.Printf("Key: %d, Value: %d\n", i, myMap[i]) // 读取map中的数据
}(i)
} // 等待所有goroutine完成
wg.Wait() // 检查map中的值是否正确(这一步是为了模拟测试)
for i := 0; i < 5; i++ {
if myMap[i] != i*10 {
t.Errorf("Expected %d but got %d", i*10, myMap[i])
}
}
}

在上面的代码中,虽然只是循环了很少的次数,就很容易出现竞争问题,错误信息类似下面的:

=== RUN   TestUnsafeMap
Key: 4, Value: 40
Fatal error: concurrent map writesKey: 0, Value: 0 Key: 2, Value: 20
Key: 1, Value: 10 t

2 、构建线程安全的 Map

在 Go 中,为了实现一个线程安全的 map 操作,可以使用 sync.Map 或者通过互斥锁(sync.Mutex)来实现。下面的示例代码是使用锁来手动实现的:


type SaleMap struct {
mu sync.Mutex
m map[int]int
} func NewSaleMap() *SaleMap {
return &SaleMap{m: make(map[int]int)}
} func (s *SaleMap) Set(key int, value int) {
s.mu.Lock()
defer s.mu.Unlock()
s.m[key] = value
} func (s *SaleMap) Get(key int) (int, bool) {
s.mu.Lock()
defer s.mu.Unlock()
value, ok := s.m[key]
return value, ok
}

然后编写单测如下:

func TestConcurrentMap(t *testing.T) {
// 创建一个线程安全的map
safeMap := NewSaleMap()
var wg sync.WaitGroup
// 启动多个goroutine并发写入和读取数据
for i := 0; i < 500000; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
safeMap.Set(i, i*10) // 向map中写入数据
}(i)
}
// 等待所有goroutine完成
wg.Wait() // 检查map中的值是否正确(这一步是为了模拟测试)
for i := 0; i < 500000; i++ {
if value, _ := safeMap.Get(i); value != i*10 {
t.Errorf("Expected %d but got %d", i*10, value)
}
}
}

这一次,循环了更多次,不会再有并发问题了。

Over!

在 Go 语言中,构造一个并发安全的 map 集合的更多相关文章

  1. 在 Go 语言中,我为什么使用接口

    强调一下是我个人的见解以及接口在 Go 语言中的意义. 如果您写代码已经有了一段时间,我可能不需要过多解释接口所带来的好处,但是在深入探讨 Go 语言中的接口前,我想花一两分钟先来简单介绍一下接口. ...

  2. [原创]C/C++语言中,如何在main.c或main.cpp中调用另一个.c文件

    C/C++语言中,如何在main.cpp中调用另一个.c文件主要有5种思路: 1.在VS2012 IDE中,将被引用的.c文件后缀名全部修改为.h,然后通过IDE的解决方案资源管理器中鼠标右键单击“头 ...

  3. Go 语言中,有时 nil 并不是一个 nil

    今天,我遇到了一个 Go FAQ.首先,作为一个小小的 Go 语言测验,看看您是否在 Go playground 中运行该程序之前就能推断出它应该打印出的内容(我已经将程序放在侧边栏中,以防它在 Go ...

  4. Java 语言中 Enum 类型的使用介绍

    Enum 类型的介绍 枚举类型(Enumerated Type) 很早就出现在编程语言中,它被用来将一组类似的值包含到一种类型当中.而这种枚举类型的名称则会被定义成独一无二的类型描述符,在这一点上和常 ...

  5. 【翻译】go语言中的map实战

    业余时间翻译,水平很差,如有瑕疵,纯属无能. 原文链接 http://blog.golang.org/go-maps-in-action go语言中的map实战 1. 简介 哈希表是计算机科学中最重要 ...

  6. C语言中setjmp与longjmp学习笔记

    C语言中setjmp与longjmp学习笔记 一.基础介绍 头文件:#include<setjmp.h> 原型:  int setjmp(jmp_buf envbuf) ,然而longjm ...

  7. 浅析C语言中assert的用法(转)

    原文地址:http://www.jb51.net/article/39685.htm 以下是对C语言中assert的使用方法进行了介绍,需要的朋友可以参考下. assert宏的原型定义在<ass ...

  8. C语言中,头文件和源文件的关系(转)

    简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析阶段 3.编译阶段,首先编译成纯汇编语句, ...

  9. C 语言中 setjmp 和 longjmp

    在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处:但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转.后面我们会看到这两个函数在处理异常 ...

  10. c语言中的scanf在java中应该怎么表达,Scanner类。

    1 java是面向对象的语言 它没有像C语言中的scanf()函数,但是它的类库中有含有scanf功能的函数 2 java.util包下有Scanner类 Scanner类的功能与scanf类似 3 ...

随机推荐

  1. 「CF 123E」Maze

    传送门 题意澄清 对于 dfs 遍历时,在某一个点进入子树的顺序并不是按输入顺序,而是假定随机选择未进入过的子树 (这纠结了我好久) . 破题思路 首先可以明确这题不能推一个 \(O(1)\) 的式子 ...

  2. C#中使用正则将字符串中某字符不区分大小写并按全字匹配替换为空

    具体代码如下所示: //将字符串中desc不区分大小写并按全字匹配替换为空 var strText = "CreatDeSce DeSc,UserName AsC"; string ...

  3. 2025年,Fantastic-admin 这款后台框架将继续引领潮流

    前言 大言不惭的取了这个标题,但作为开发了 4 年多的 Fantastic-admin 的作者,回顾这一路走来,从一开始被指责抄袭,到现在拥有数百名付费用户和几十家付费企业.我认为我的开发理念应该是得 ...

  4. Vulnhun靶机-kioptix level 4-sql注入万能密码拿到权限ssh连接利用mysql-udf漏洞提权

    一.环境搭建 然后选择靶机所在文件夹 信息收集 本靶机ip和攻击机ip 攻击机:192.168.108.130 靶机:192.168.108.141 扫描ip 靶机ip为:192.168.108.14 ...

  5. Hive - [01] 概述

    一.Hive是什么 是Facebook开源,用于解决海量结构化日志的数据统计工具. 是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能. Hive处理的数 ...

  6. DeepSeek 全套资料pdf合集免费下载(持续更新)

    有很多朋友都关注DeepSeek相关使用的教程资料,本站也一直持续分享DeepSeek 学习相关的pdf资料,由于比较零散,这篇文章主要就是做一个汇总,并且持续更新,让大家可以及时获取下载最新的相关D ...

  7. Ubuntu22.04双网卡调试

    最近捡起正点原子的linux开发板,又开始了linux的学习,这条路走走停停的,隔了一年时间很多积累的东西都忘了.打开VMware虚拟机发现网络也连接不上了,我的印象中去年是把虚拟机的双网卡配置好了, ...

  8. sap 管理--企业解决方案 -设备管理

    1.什么是sap 管理 2.设备管理管的是什么 3.设备的几种状态 4.设备bom(物料清单) 5.测量点计数器 1.什么是sap 管理 System Applications and Product ...

  9. pytest 框架使用规则

    使用pytest 注意 有时候常常会调用时文件未执行,就是没注意命名规范 如何调用-命令行调用 pytest 批量运行测试用例 单个用例调试成功后,接下来我们要进行所有脚本统一执行 我要执行testc ...

  10. MS17_010漏洞利用,渗透win7,拿到桌面的flag

    关于使用MS17_010来攻击WIN7: 我们先ping一下win7的ip看看是否可以ping通(ping不通的可以关闭win7的防火墙),然后我们用nmap扫一下看看靶机有什么漏洞 nmap --s ...