Go语言中的map使用及并发安全

首先,Go语言的map底层是哈希表,而C++map的底层是红黑树,C++unordered_map的底层才是哈希表。所以增删改查的时间复杂度都是O(1)。当我们使用的时候需要注意以下几点:

  1. map是引用类型,如果两个map同时指向一个底层,那么一个map的变动会影响到另一个map,这一点需要特殊注意。

  2. map的零值(Zero Value)是nil,对nil map进行任何添加元素的操作都会触发运行时错误(panic)。因此,使用必须先创建map,使用make函数,例如:

    func f(int n) {m := make([]map[int]int, n)for i := range m {m[i] = make(map[int]int) // m中的所有map在使用前必须初始化}
    }
    
  3. map的键可以是任何可以用==!=操作符比较的类型,比如字符串、整数、浮点数、复数和布尔类型等。但是,slice, map, function等类型不可以作为map的键。

  4. map在使用过程中不保证顺序遍历,每次遍历的结果可能会不同,这一点和C++unordered_map相似。

  5. map进行的所有操作,增删改都不是线程安全的,如果在一个goroutine中修改了map,同时在另一个goroutine中读取了map,可能会触发concurrent map read and map write的错误。

并发安全:

由上述的第五点可知,Go语言的map不是并发安全的。并发情况下,对于map的读写操作都需要加锁,或者会引起竞争条件甚至导致程序崩溃。为了在并发环境下使用map,我们可以使用sync包中的sync.RWMutex读写锁,或者使用sync.Map

比如,我们可以使用读写锁来保证多个goroutine都可以访问同一个map:

var m = make(map[string]int)
var mutex = &sync.RWMutex{}
// 基本使用流程与C++和Java中锁的流程类似
func write(key string, value int) {mutex.Lock()m[key] = valuemutex.Unlock()
}func read(key string) (int, bool) {mutex.Lock()defer mutex.RUnlock()value, ok := m[key]return value, ok
}

再比如,我们也可以使用sync.Map{}完成并发控制:

func f() {m := sync.Map{}list := []string{"A", "B", "C", "D"}wg := sync.WaitGroup{}// 添加协程,等待协程完成for i := 0; i < 20; i++ {// 启动20组协程wg.Add(1)// 添加协程数量,一次只启动一个go func() {defer wg.Done() // 协程结束之后 wg - 1for _, item := range list {// 存在则 + 1, 不存在则初始化为1value, ok := m.Load(item)if !ok {value, _ = m.LoadOrStore(item, 0)}val := value.(int) + 1m.Store(item, val)}}()}wg.Wait() // 等待所有协程完成m.Range(func(k, v any) bool {fmt.Println(k, v)return true})fmt.Println(m)
}

最后给大家推荐一个LinuxC/C++高级架构系统教程的学习资源与课程,可以帮助你有方向、更细致地学习C/C++后端开发,具体内容请见 https://xxetb.xetslk.com/s/1o04uB

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

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

相关文章

Facebook的声音:听见社交媒体的心跳

社交媒体如今已经成为人们日常生活中不可或缺的一部分&#xff0c;而Facebook作为其中的佼佼者&#xff0c;承载着数以亿计的用户的交流、分享和连接。在这个信息爆炸的时代&#xff0c;Facebook的声音就像是社交媒体的心跳&#xff0c;传递着无数个体的情感、思想和生活。本文…

从0到1手写注册中心Registry之集群选主

一、领域对象 Cluster&#xff1a;描述集群信息 port描述当前服务端口&#xff1b;host描述当前服务主机&#xff1b;myself描述当前服务本身&#xff1b;servers描述当前服务集群列表registryConfigProperties配置信息&#xff1b;executor定时任务&#xff0c;负责更新服务…

Java 网络编程之TCP(四):基于NIO中的selector实现服务端,解决客户端异常断开导致服务端不断读取OP_READ问题

上一篇文章中&#xff0c;没有使用Selector&#xff0c;实习服务端的读取多个客户端的数据&#xff1b;本文先使用Selector实现读取多个客户单数据的功能&#xff0c;然后做些扩展。 一、基于NIO Selector读取多个客户的数据 1.服务端&#xff1a;基于Selector处理客户端的连…

windows pytorch安装

安装环境 WindowsAnacondaCudacuDNN Linux和Windows操作系统的安装存在差异&#xff0c;步骤会有所不同&#xff0c;本教程主要针对Windows系统进行示例。 Anaconda集成了许多方便的包和工具&#xff0c;使用会更加方便&#xff0c;特别适合科学计算&#xff0c;深度学习的数…

WSL及UBUNTU及xfce4安装

如何拥有Linux服务器&#xff1f; wsl 是适用于 Linux 的 Windows 子系统&#xff08;Windows Subsystem for Linux&#xff09;。是一个为在Windows 10和Windows Server 2019上能够原生运行Linux二进制可执行文件&#xff08;ELF格式&#xff09;的兼容层&#xff0c;可让开发…

LLM之RAG理论(十一)| 面向生产的RAG应用程序的12种调整策略指南

本文对文本RAG涉及到的主要12种关键“超参数”进行简单总结&#xff0c;主要包括摄取阶段&#xff08;数据清洗、数据分块、embedding模型选择、元数据过滤、多重索引和索引算法&#xff09;和推理阶段【检索和生成】&#xff08;查询转换、检索参数、高级检索策略、重排序、大…

C语言【动态内存】

1.为什么要有动态内存 我们现在掌握的内存开辟方法有&#xff1a; int val 20;//在栈空间开辟4个字节 char str[10]{0};//在栈空间开辟10个字节的连续的空间但是上述的方式有两个点要注意&#xff1a; 1.空间开辟的大小是固定的 2.数组在申明的时候&#xff0c;一定要指定数…

数据驱动,敏捷前行|MongoDB线下技术沙龙-杭州站活动

扫描海报中二维码或点击阅读原文&#xff0c;报名参加阿里云MongoDB在5月11日杭州举办的【数据驱动&#xff0c;敏捷前行——MongoDB企业开发加速器】线下沙龙活动&#xff0c;与MongoDB专家以及其他游戏行业同行一起探讨轻松获得游戏数据库高可用性和弹性的方法&#xff01; 在…

运维实施工程师常用技术面试题(系统与软件实施)

常用技术面试题(系统与软件实施) 9.1 计算机基础 你熟悉的远程有哪些方法?各种方法应该怎么配置? (1)最简单的QQ上有,打开对话框 上边有个 “应用”图标 点击“远程协助”。(2)系统自带的远程桌面服务,右击我的电脑—属性,点远程,把两个够都打上去。 (3)远程协助…

赶紧收藏!2024 年最常见 100道 Java 基础面试题(十九)

上一篇地址&#xff1a;赶紧收藏&#xff01;2024 年最常见 100道 Java 基础面试题&#xff08;十八&#xff09;-CSDN博客 三十七、守护线程是什么&#xff1f; 守护线程&#xff08;Daemon Thread&#xff09;是Java中的一种特殊类型的线程&#xff0c;它的目的是为其他线程…

安卓获取SHA

1&#xff1a;安卓通过签名key获取SHA 方式有两种&#xff0c; 1、电脑上来存在eclipse的用户或正在使用此开发工具的用户就简单了&#xff0c;直接利用eclipse 走打包流程&#xff0c;再打包的时候选择相应的签名&#xff0c;那么在当前面板的下面便会出现签名的相关信息。 2、…

springboot615基于springboot的旅游出行指南_655ms--论文

springboot615基于springboot的旅游出行指南_655ms--论文 springboot615基于springboot的旅游出行指南

23 重构:烟囱式、平台化、中台化的架构

上一讲里&#xff0c;我们介绍了两大类型的系统升级重构方案&#xff0c;还介绍了如何进行重构版本的上线&#xff0c;以及如何平滑地完成新老版本切换的方案。在本讲里&#xff0c;将会具体介绍如何判断系统发展到什么阶段需要重构&#xff0c;以及如何实施重构。 系统稳定性…

AutoBackgroundBackButton 在ScrollView上方自动根据返回键按钮下方内容动态改变颜色。自动变色返回键

在日常有时候有一些为了优化体验的需求。AutoBackgroundBackButton 一个可以根据按钮下方背景颜色动态的改版返回键自定义ImageView。这里只展示了黑白切换方式&#xff0c;你如果还有其他需求可以参考颜色校验来自己实现切换对应颜色按钮。【例如白色背景展示黑色样式&#xf…

【Git】修改提交记录的日期和提交信息

1. 查看日志 git log 2. 修改最近一次提交的时间 git commit --amend --date"2024-05-01T09:30:000800" -am ":memo: 更新 TODO.md" 3. 修改最近一次提交的时间并使用指定提交记录的信息 git commit --amend --date"2024-05-01T09:30:000800&quo…

深入了解Java中的Thread类

在Java编程中&#xff0c;Thread类是一个核心的类&#xff0c;用于创建和管理线程。线程是程序执行的最小单元&#xff0c;多线程编程可以提高程序的并发性和效率。 本文将深入介绍Java中的Thread类&#xff0c;包括其基本概念、创建线程的方法、线程状态的转换、线程同步与通…

Python urllib 爬虫入门(1)

本文主要为Python urllib类库函数和属性介绍及一些简单示例。 目录 urllib爬取网页 简单示例 写入文件 其他读取方法 readline函数 readlines函数 response属性 当前环境信息 返回状态码 返回url地址 对url进行编码与解码 写入文件 总结 urllib爬取网页 通过pyth…

保障互联网基础:深度解析DNS安全

目录 前言 一. DNS 概述 二. DNS 安全威胁 1..DNS欺骗 2.DNS缓存污染 3.DNS放大攻击 4.DNS隧道 5.危害 5.1数据盗窃和财务损失 5.2声誉损害和品牌蚀刻 5.3合规和监管问题 5.4系统停机和生产力损失 三. DNS 安全解决方案 1.DNSSEC&#xff08;域名系统安全扩展&…

PotatoPie 4.0 实验教程(35) —— FPGA实现摄像头图像二值化膨胀效果

手机扫码 链接直达 https://item.taobao.com/item.htm?ftt&id776516984361 什么是图像二值化膨胀&#xff0c;有什么作用&#xff1f; 图像二值化膨胀是图像处理中的一种基本操作&#xff0c;它用于扩展和增强二值图像中的白色区域。具体而言&#xff0c;二值化膨胀操作…

【论文笔记】Training language models to follow instructions with human feedback A部分

Training language models to follow instructions with human feedback A 部分 回顾一下第一代 GPT-1 &#xff1a; 设计思路是 “海量无标记文本进行无监督预训练少量有标签文本有监督微调” 范式&#xff1b;模型架构是基于 Transformer 的叠加解码器&#xff08;掩码自注意…