返回顶部
首页 > 资讯 > 后端开发 > GO >GoMap并发冲突预防与解决
  • 377
分享到

GoMap并发冲突预防与解决

GoMap并发冲突GoMap 2022-12-15 12:12:54 377人浏览 八月长安
摘要

目录背景并行单元测试支持并发的 Mapsync.RWMutexsync.Map背景 关于 Go 语言的 Map,有两个需要注意的特性: Map 是并发读写不安全的,这是出于性能的考

背景

关于 Go 语言的 Map,有两个需要注意的特性:

  • Map 是并发读写不安全的,这是出于性能的考虑;
  • Map 并发读写导致的错误,无法使用 recover 捕获。

后者意味着,只有出现并发读写的问题,服务就会挂掉。

这两个特性可能大家都知道,可即使有这个共识,我还是见过这个问题导致的事故。

事故的大致情况是,一个人封装了map的读写,没有使用。另一个人开协程读写 map。而测试环境请求量小,不一定会导致崩溃,于是,这个问题就留到生产环境才出现了。

除了靠开发者自觉和 code review,还能怎么预防这种情况呢?我觉得在单元测试加入并行测试也很重要。

并行单元测试

单元测试默认不是并发的,比如下面的单测,是可以通过的:

func TestConcurrent(t *testing.T) {
    var m = map[string]int{}
    // 写 map
    t.Run("write", func(t *testing.T) {
      for i := 0; i < 10000; i++ {
        m["a"] = 1
      }
    })
    // 读 map
    t.Run("read", func(t *testing.T) {
      for i := 0; i < 10000; i++ {
        _ = m["a"]
      }
    })
}

但是我们的期望是,上面的单测不通过,该如何解决呢?

testing.T 有一个 Parallel 方法,它表示当前测试会和其他测试并行运行。 如果参数有-test.count-test.cpu,一个测试可能运行多次,同个测试的多个运行实例,不会并行运行。

我们给上面的单测,加上t.Parallel():

func TestConcurrent(t *testing.T) {
    var m = map[string]int{}
    t.Run("write", func(t *testing.T) {
      // 加上并行
      t.Parallel()
      for i := 0; i < 10000; i++ {
        m["a"] = 1
      }
    })
    t.Run("read", func(t *testing.T) {
      // 加上并行
      t.Parallel()
      for i := 0; i < 10000; i++ {
        _ = m["a"]
      }
    })
}

这次执行就会报错:

fatal error: concurrent map read and map write

支持并发的 Map

让 Map 支持并发读写并不麻烦,常见的做法有:

  • 操作 map 的时候,加上读写锁 sync.RWMutex
  • 使用 sync.Map。

sync.RWMutex 大家用得可能比较多。这里简单给个demo。

sync.RWMutex

我们给上面的单测加上锁,这次运行就能通过了。

func TestConcurrent(t *testing.T) {
	var m = map[string]int{}
	//  定义锁,零值就可以使用
	var mu sync.RWMutex
	t.Run("write", func(t *testing.T) {
		t.Parallel()
		for i := 0; i < 10000; i++ {
			// 锁
			mu.Lock()
			m["a"] = 1
			// 解锁
			mu.Unlock()
		}
	})
	t.Run("read", func(t *testing.T) {
		t.Parallel()
		for i := 0; i < 10000; i++ {
			// 锁
			mu.Lock()
			_ = m["a"]
			// 解锁
			mu.Unlock()
		}
	})
}

本文的重点介绍一下Go标准库自带的,支持并发读写的 map:sync.Map

sync.Map

sync.Map 就是线程安全版的 map[interface{}]interface{},零值可以直接使用,值不能复制。它主要用于以下场景:

  • 当同一个 key 的值,写少读多的时候;
  • 但多个 goroutines 读写或修改一系列不同的key的时候。

上面两种场景中,比起带Mutex(或RWMutex)的map,sync.Map 会大大减少锁的竞争。

sync.Map 提供的方法不多,这里列出一些。注意的是,any 是 go 1.18 中 interface{}的别名。

Store,设置 key-value。

func (m *Map) Store(key, value any)

Load, 根据 key 读取 value。

func (m *Map) Load(key any) (value any, ok bool)

Delete,删除某个key。

func (m *Map) Delete(key any)

Range,遍历所有key, 如果f返回false,会停止遍历。

func (m *Map) Range(f func(key, value any) bool)

还有 LoadAndDelete(读后删除)、LoadOrStore(读key,不存在时设置)。

我们给上面的单测,使用sync.Map,测试也可以通过。

func TestConcurrent(t *testing.T) {
	// 可以使用零值
	var m sync.Map
	t.Run("write", func(t *testing.T) {
		t.Parallel()
		for i := 0; i < 10000; i++ {
			// 写
			m.Store("a", 1)
		}
	})
	t.Run("read", func(t *testing.T) {
		t.Parallel()
		for i := 0; i < 10000; i++ {
			// 读
			v, ok := m.Load("a")
			if ok {
				_ = v.(int)
			}
		}
	})
}

参考

pkg.go.dev/synC#Map

以上就是Go Map并发冲突预防与解决的详细内容,更多关于Go Map并发冲突的资料请关注编程网其它相关文章!

您可能感兴趣的文档:

--结束END--

本文标题: GoMap并发冲突预防与解决

本文链接: https://lsjlt.com/news/174909.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • GoMap并发冲突预防与解决
    目录背景并行单元测试支持并发的 Mapsync.RWMutexsync.Map背景 关于 Go 语言的 Map,有两个需要注意的特性: Map 是并发读写不安全的,这是出于性能的考...
    99+
    2022-12-15
    Go Map并发冲突 Go Map
  • Python 接口 api 并发:如何解决并发冲突?
    在现代的应用程序开发中,对于高并发处理的需求越来越普遍。Python 作为一种高效的编程语言,也提供了很多处理并发的方法。其中,接口 api 并发是一种非常常见的应用场景。本文将介绍如何使用 Python 处理接口 api 并发时可能出现...
    99+
    2023-07-19
    接口 api 并发
  • Git合并冲突怎么解决
    本篇内容主要讲解“Git合并冲突怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Git合并冲突怎么解决”吧!假设我的远程存储库已被我的两个团队成员user...
    99+
    2024-04-02
  • git如何解决合并冲突
    这篇文章主要介绍“git如何解决合并冲突”,在日常操作中,相信很多人在git如何解决合并冲突问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”git如何解决合并冲突”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-07-02
  • 使用Axios拦截器解决前端并发冲突
    这篇文章主要讲解了“使用Axios拦截器解决前端并发冲突”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“使用Axios拦截器解决前端并发冲突”吧!背景并发冲突...
    99+
    2024-04-02
  • Couchbase如何处理并发访问和冲突解决
    Couchbase是一个面向文档的NoSQL数据库,它使用乐观并发控制来处理并发访问和解决冲突。 在Couchbase中,每个文档都...
    99+
    2024-04-09
    Couchbase
  • 解决docker与vmware的冲突问题
    1、docker启动问题: 问题解决: 需要开启Hyper-V,(开启方法:控制面板->程序->程序和功能->启动或关闭Windows功能,然后再重新启动电脑) ...
    99+
    2024-04-02
  • 怎么解决Git合并冲突的问题
    本篇内容介绍了“怎么解决Git合并冲突的问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!合并并不仅仅是简单的文件添加、移除的操作,Git ...
    99+
    2023-06-04
  • golang函数并发控制中死锁与饥饿的预防与解决
    go 中死锁和饥饿:预防与解决死锁:协程相互等待而无法进行的操作,使用 runtime.setblockprofilerate 函数检测。预防死锁:使用细粒度加锁、超时、无锁数据结构,防...
    99+
    2024-04-24
    死锁 饥饿 golang
  • spring security与corsFilter冲突的解决方案
    目录spring security与corsFilter冲突问题解决方案springboot解决跨域问题(CorsConfig)项目实践小结一下spring security与cor...
    99+
    2024-04-02
  • 如何解决docker与vmware的冲突问题
    这篇文章给大家分享的是有关如何解决docker与vmware的冲突问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1、docker启动问题:问题解决:需要开启Hyper-V,(开启方法:控制面板->程序-...
    99+
    2023-06-14
  • Android之事件分发机制与冲突详解
    在日常的开发过程中,我们往往会在同一个界面中出现内外两层或者多层View同时滑动的现象,这个时候往往**会出现滑动冲突。面对滑动冲突,很多开发人员不知道从哪里入手,**即便稍微有点思...
    99+
    2024-04-02
  • 如何解决进行git合并造成的冲突
    如何解决进行git合并造成的冲突 场景: 在我们在参与项目开发的时候,通常会创建公共的文件,但是当我们编码完成,使用git进行分支合并时,往往会出现合并冲突,也就是负责不同部分的开发人员会对同一...
    99+
    2023-09-21
    git github
  • 如何解决Go语言中的并发内存访问冲突问题?
    如何解决Go语言中的并发内存访问冲突问题?在Go语言中,我们可以使用goroutine来实现并发编程,这无疑给我们带来了更强大的性能和并行处理能力。然而,并发编程也会引发一些问题,其中最常见的就是内存访问冲突。内存访问冲突问题是指多个gor...
    99+
    2023-10-22
  • gateway与spring-boot-starter-web冲突问题的解决
    gateway与spring-boot-starter-web 冲突 环境: SpringCloud 版本 ---- Finchley.SR2 SpringBoot 版本 ---- ...
    99+
    2024-04-02
  • Bootstrap与UEditor中Css冲突问题怎么解决
    这篇“Bootstrap与UEditor中Css冲突问题怎么解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面...
    99+
    2024-04-02
  • 解决Hmily与Feign冲突报错 NullPointerException的问题
    目录Hmily与Feign冲突报错 NullPointerException解决方法java.lang.NullPointerException出现的几种原因及解决出现的原因Hmil...
    99+
    2024-04-02
  • oracle字段与关键字冲突如何解决
    当Oracle字段与关键字冲突时,可以通过以下几种方式来解决:1. 使用引号包裹字段名:将冲突的字段名用双引号或方括号包裹起来,例如...
    99+
    2023-08-29
    oracle
  • 解决MongoDB技术开发中遇到的并发冲突问题的方法研究
    解决MongoDB技术开发中遇到的并发冲突问题的方法研究引言:随着互联网技术的发展,数据库的并发操作已成为现代应用开发中的一个重要问题。在MongoDB技术开发过程中,也常常会遇到并发冲突的问题。本文将研究解决MongoDB并发冲突问题的方...
    99+
    2023-10-22
    MongoDB并发冲突解决方法研究 MongoDB并发冲突解决方法探究
  • Android ViewPager自定义轮播图并解决播放冲突
    本文实例为大家分享了Android ViewPager自定义轮播图,并解决播放冲突,供大家参考 首先介绍一下这篇小代码: 注释全面,简单易学,适用初学者,图片自拟!!! 一定要将Ar...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作