Golang 线程安全与 sync.Map_go 中使用 sync.map 实现线程安全缓存-程序员宅基地

技术标签: golang  

前言

线程安全通常是指在并发环境下,共享资源的访问被适当地管理,以防止竞争条件(race conditions)导致的数据不一致
Go语言中的线程安全可以通过多种方式实现

实现方式

  1. 互斥锁(Mutexes)
    Go的sync包提供了Mutex和RWMutex类型来确保在一个时间点只有一个协程可以访问某个资源
import "sync"

var mu sync.Mutex
var sharedResource map[string]int

func updateResource(key string, value int) {
    
    mu.Lock()         // 加锁
    sharedResource[key] = value
    mu.Unlock()       // 解锁
}
  1. 原子操作(Atomic operations)
    sync/atomic包提供了一系列原子操作函数,可用于管理基本数据类型的并发访问
import "sync/atomic"

var count int64

func increment() {
    
    atomic.AddInt64(&count, 1) // 原子地增加计数
}
  1. 通道(Channels)
    通过使用通道,可以在协程之间安全地传递数据。当数据通过通道从一个协程传递到另一个协程时,不需要额外的同步机制
ch := make(chan int)

// 发送者
go func() {
    
    ch <- 42
}()

// 接收者
go func() {
    
    value := <-ch
    fmt.Println(value)
}()
  1. 不可变性(Immutability)
    不修改数据可以自然地避免并发问题。设计数据结构和算法时,尽可能使数据不可变,可以减少同步的需要

  2. 其他同步原语
    sync包还提供了其他同步原语,如WaitGroup、Once、Cond等,可以用来同步协程的不同行为

使用上述任何一种机制时,都需要仔细设计代码以避免死锁、活锁或饥饿等问题。在Go中,可以使用go run -race命令来检测代码中的竞争条件

sync.Map

sync.Map 是一个线程安全的映射(map),它是在 sync 包中提供的。与使用互斥锁来保护普通的 map 不同,sync.Map 使用了一种无锁的技术,特别适用于以下两种场景:

  1. 当给定键的条目只写入一次但读取多次时,比如在全局缓存中
  2. 当多个协程读取、写入和覆盖不相交的键集的条目时

sync.Map 提供了一些内置方法来操作线程安全的键值对:

  • Store(key, value): 存储键值对
  • Load(key): 根据键获取值
  • LoadOrStore(key, value): 获取或存储键值对。如果键已经存在,则返回现有的键值对和 false;如果不存在,则存储并返回键值对和 true
  • Delete(key): 删除键值对
  • Range(f func(key, value interface{}) bool): 遍历所有键值对,对每个键值对执行给定的函数 f

看下基本用法

import (
    "fmt"
    "sync"
)

func main() {
    
    var sm sync.Map

    // 存储键值对
    sm.Store("hello", "world")
    sm.Store(1, 3)

    // 读取键对应的值
    if value, ok := sm.Load("hello"); ok {
    
        fmt.Println("hello:", value)
    }

    // 删除键
    sm.Delete("hello")

    // 遍历所有键值对
    sm.Range(func(key, value interface{
    }) bool {
    
        fmt.Println(key, value)
        return true // 继续遍历
    })
}

请注意,尽管 sync.Map 提供了线程安全的操作,但是它的性能通常会比使用互斥锁保护的普通 map 差,因此只推荐在上述特定场景中使用

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/e5pool/article/details/135470385

智能推荐

waves2Foam系列:1.安装-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏6次。waves2Foam 的安装waves2Foam的编译不算很难,其中可能会遇见一些错误。但如果仔细观察输出的log的话,是比较容易发现错误的。本文使用Ubuntu 18.04 OpenFOAM 版本为3.0.1以及1912其中3.0.1的安装采用的是源代码本地编译,而1912是通过预编译deb包直接安装的。本文不讲述OpenFOAM安装的细节。安装waves2Foam首先是下载依赖:$ sudo apt install libgsl-dev gfortran subversion git_waves2foam

小功能:java导出excel,并与附件打包zip,excel中每条记录用超链接关联附件目录_excel java 打包-程序员宅基地

文章浏览阅读2.7k次,点赞3次,收藏16次。java导出excel,并与附件打包zip,excel中每条记录用超链接关联附件目录。_excel java 打包

使用Newtonsoft.Json 解决Json日期格式问题_mvcnewtonsoftjsonoptions 日期格式配置-程序员宅基地

文章浏览阅读5.7k次。介绍Asp.Net MVC默认是使用JavaScriptSerializer做Json序列化的,不好用。而且JavaScriptSerializer无法处理循环引用,对日期的格式化不友好。例如对当前日期序列化后的效果是这样的:【CreateTime: "/Date(1521983727837)/"】 这样的日期我们很难看懂而且JavaScriptSerializer对一个对象的序列化,序列化后的j..._mvcnewtonsoftjsonoptions 日期格式配置

[c++] 基类与派生类的构造与析构顺序-程序员宅基地

文章浏览阅读514次。  昨天做了网易的实习生笔试(一首凉凉送给自己),其中有道问答题是这样的 1 #include<iostream> 2 using namespace std; 3 class A 4 { 5 public: 6 A(){cout<<"A"<<endl;} 7 ~A(){cout<<"~A"&..._输出基类与派生类的构造和析构顺序

CountdownEvent-程序员宅基地

文章浏览阅读131次。 CountdownEvent lets you wait on more than one thread. The class is new to Framework 4.0 and has an efficient, fully managed implementation. To use the class, instantiate it with the number of threads..._using (var countdown = new countdownevent(

利用MTCNN和facenet实现人脸检测和人脸识别-程序员宅基地

文章浏览阅读8.7k次,点赞8次,收藏78次。利用MTCNN和facenet实现人脸检测和人脸识别 人脸检测和人脸识别技术算是目前人工智能方面应用最成熟的技术了。本博客将利用mtcnn和faceNet搭建一个实现人脸检测和人脸识别的系统。基本思路也很简单,先利用mtcnn的进行人脸检测,当然也可以使用其他的人脸检测方法,如Dilb,OpenCV,OpenFace人脸检测等等,然后再利用faceNet进行人脸识别,f......_mtcnn和facenet

随便推点

Android Studio 实现地图定位(移动开发技术作业)_android stdio 定位波罗地海-程序员宅基地

文章浏览阅读1w次,点赞14次,收藏141次。一、项目要求1.根据百度地图提供的开发者文档,创建项目实现地图。2.可以提供地图显示,定位具体位置的功能。二、项目功能展示三、项目具体实现方法1.创建项目及Android studio基础配置在android studio 中创建一个新的空白项目打开浏览器搜索百度地图进入开放平台,然后点开开发文档选择地图SDK在文档底部根据提示完成前两个步骤,如果已有百度账号可以跳过注册直接申请称为百度地图开发者完成前两步的注册,申请开发者之后选择获取服务密钥(如果之前之前做过相关开发项目已经成为百度地_android stdio 定位波罗地海

微信消息推送协议简单分析_微信的消息通知是长链接吗-程序员宅基地

文章浏览阅读8.9k次。【结论】1) Android微信客户端和微信服务器A的(443端口)维持一个TCP长连接;定时向该服务器发送心跳;2) 有新消息时,微信服务器A通知Android微信客户端;后者和微信服务器B建立新的TCP短连接,并获得数据;3) 心跳间隔比较长,约300秒左右; 【协议分析】 分析涉及到两个微信服务器:服务器一:183.61.49.148 Andro_微信的消息通知是长链接吗

使用Mock框架JMockit进行单元测试-程序员宅基地

文章浏览阅读4.2k次,点赞2次,收藏26次。关于单元测试,我们先上一段代码,如下示例:public String sayHello() { Locale locale = Locale.getDefault(); if (locale.equals(Locale.CHINA)) { // 在中国,就说中文 return "你好,世界!"; } else { // 在其它国家,就说英文 return "H...

解密:古人八拜之交指的是哪八拜?_举杯对饮,八拜之交代表故事是什么生肖故事-程序员宅基地

文章浏览阅读3.7k次。_举杯对饮,八拜之交代表故事是什么生肖故事

CTF 学习笔记_ctf笔记-程序员宅基地

文章浏览阅读4.3k次,点赞7次,收藏60次。CTF起源于1996年DEFCON全球黑客大会,以替代之前黑客们通过互相发起真实攻击进行技术比拼的方式。WordPress是利用PHP开发的博客平台,用户可以在支持PHP和MySQL数据库的服务上架设属于自己的网站。也可以把WordPress当做一个内容管理系统(CMS)来使用。WordPress是一款个人博客系统,并逐步演化成一款内容管理系统软件,它是使用PHP语言和MySQL数据库开发的,用户可以在支持PHP和MySQL数据库的服务器上使用自己的博客。_ctf笔记

python+OpenCV笔记(二十七):反投影图像-程序员宅基地

本文介绍了Python和OpenCV中的反投影图像的概念、工作原理和代码编写。同时提到了直方图和直方图均衡化的相关知识。