Golang|单机并发缓存

devtools/2025/1/18 2:58:27/
var m sync.Mutex
//sync.Mutex 是一个互斥锁,可以由不同的协程加锁和解锁。
//sync.Mutex 是 Go 语言标准库提供的一个互斥锁
//当一个协程(goroutine)获得了这个锁的拥有权后,其它请求锁的协程(goroutine)就会阻塞在 Lock() 方法的调用上,直到调用 Unlock() 锁被释放。var set = make(map[int]bool, 0)func printOnce(num int) {m.Lock()defer m.Unlock()if _, exist := set[num]; !exist {fmt.Println(num)}set[num] = true
}func main() {for i := 0; i < 10; i++ {go printOnce(100)}time.Sleep(time.Second)
}
  • 接下来考虑用 sync.Mutex 封装 LRU 缓存淘汰策略的几个方法,使之支持并发的读写。
  • 抽象了一个 只读 数据结构 ByteView 用来表示缓存值,是 GeeCache 主要的数据结构之一。
  • ByteView 是对实际缓存的⼀层封装,因为实际的缓存值是⼀个 byte 切⽚存储的,⽽切⽚的底层是⼀个指向底层数组的指针,⼀个记录⻓度的变量和⼀个记录容量的变量。
  • 为什么要用 byte 切片?因为 byte 支持任意数据类型的存储。
    • byteuint8 的别名:在 Go 中,byte 实际上是 uint8 的一种别名,它表示 0255 范围内的无符号整数。
    • 在计算机中,所有数据(无论是文本、图片、视频还是其他格式)最终都会以二进制形式存储和处理。二进制数据可以被视为一系列字节([]byte),而 byte 则是这种数据的基本单位。
b := []byte{'a', 'b', 'c'}
// b的底层数据结构如下:
// 一个指针指向底层数组 [a, b, c]
// len(b) = 3
// cap(b) b的容量,取决于底层数组的大小
  • 如果获取缓存值时直接返回缓存值的切⽚,那个切⽚只是原切⽚三个变量的拷⻉,真正的缓存值就可能被外部恶意修改。
  • 这里可能一开始会有点难理解:为什么直接返回切片有问题?
    • 切片返回的是一个浅拷贝:切片的复制只会复制切片的三个元数据(指针、长度、容量),而不会复制底层数组;新切片和原切片共用同一个底层数组。
    • 缓存值可能被修改:如果外部通过返回的切片修改数据,实际上会直接修改底层数组的内容。
func main() {cache := []byte{'x', 'y', 'z'}external := cache // 浅拷贝,仅复制指针、长度和容量external[0] = 'a' // 修改 external 也会影响 cachefmt.Println(string(cache)) // 输出 "ayz"
}
  • 所以⽤ ByteView 进⾏⼀层封装,返回缓存值时的 ByteView 则是⼀个原切⽚的深拷⻉。
  • 如何通过 ByteView 解决问题?
    • ByteView 的设计目的是通过深拷贝避免直接暴露底层数组。
    • 封装数据:ByteView 持有一个不可直接访问的字段 b,存储了原始缓存数据的拷贝。外部无法直接获取和修改底层数据。
    • 深拷贝的实现:通过 cloneBytes 函数,对底层数据进行深拷贝——新建一个独立的字节数组,将原始数据逐字节复制到新数组中。
    • 只读访问:通过 ByteSliceString 等方法,外部只能访问数据的副本或只读视图,无法影响原始数据。
package geecache// A ByteView holds an immutable view of bytes.
type ByteView struct {b []byte
}// Len returns the view's length
func (v ByteView) Len() int {return len(v.b)
}// ByteSlice returns a copy of the data as a byte slice.
func (v ByteView) ByteSlice() []byte {return cloneBytes(v.b)
}// String returns the data as a string, making a copy if necessary.
func (v ByteView) String() string {return string(v.b)
}func cloneBytes(b []byte) []byte {c := make([]byte, len(b))copy(c, b)return c
}
  • 接下来为 lru.Cache 添加并发特性。

http://www.ppmy.cn/devtools/151444.html

相关文章

Spring Boot中使用AOP实现权限管理

权限管理的实现方法有很多种&#xff0c;也有很多集成不错的框架。现在用AOP和自定义注解实现一个简单易理解的权限管理~ 默认已经有做好了RBAC(role based access control)&#xff0c;基于角色的访问控制。就是数据库中已经有了用户表&#xff0c;角色表&#xff0c;权限表…

MiniCPM-o 2.6:开源大型语言模型在多模态任务上超越GPT-4o和Claude 3.5

MiniCPM-o 2.6是一款开源的大型语言模型&#xff08;LLM&#xff09;&#xff0c;其在多模态任务上的表现令人瞩目&#xff0c;成功超越了GPT-4o和Claude 3.5等业界知名模型。以下是对MiniCPM-o 2.6的详细介绍&#xff1a; 一、卓越的多模态能力 MiniCPM-o 2.6采用了先进的端…

ElasticSearch的劈山斧-自定义评分

ElasticSearch自定义评分 一、适用的场景 1.基本介绍 ES的使用中&#xff0c;ES会对我们匹配文档进行相关度评分。但对于一些定制化的场景&#xff0c;默认评分规则满足不了我们的要求。这些定制化场景&#xff0c;ES也是推出了自定义评分方式来进行支持。可以使用ES提供的一…

Go语言之路————条件控制:if、for、switch

Go语言之路————if、for、switch 前言ifforswitchgoto和label 前言 我是一名多年Java开发人员&#xff0c;因为工作需要现在要学习go语言&#xff0c;Go语言之路是一个系列&#xff0c;记录着我从0开始接触Go&#xff0c;到后面能正常完成工作上的业务开发的过程&#xff0…

大模型——RAG

什么是RAG RAG&#xff08;Retrieval Augmented Generation,检索增强生成&#xff09;&#xff0c;LLM在回答问题或生成文本时&#xff0c;先会从大量文档中检索出相关的信息&#xff0c;然后基于这些信息生成回答或文本&#xff0c;从而提高预测质量。 R:检索器模块 在RAG中…

云手机技术怎么实现的?

前言 随着亚矩阵云手机在跨境电商、海外社媒矩阵搭建、出海运营、海外广告投放、国内新媒体矩阵运营、品牌应用矩阵运营等领域内的普及和使用&#xff0c;云手机的理念已经被越来越多人所接受和认同。今天我们就一起来浅析一下&#xff0c;到底云手机的技术是怎么实现的&#…

windows安装docker

安装 首先确保windows启用Hyper-V&#xff0c;子linux系统和虚拟机平台&#xff0c;且cpu开启虚拟化 重启等待应用生效 安装doxker desktop 下载链接 打开cmd&#xff0c;输入docker version查看安装情况 在服务类型查看docker服务是否启动&#xff0c;不是进入服务修改为自…

LDN的蓝牙双模键盘帮助文档

文档索引 已支持的PCB列表(仅列出少部分)&#xff1a;键盘特性硬件软件键盘以及驱动蓝牙模式USB模式 驱动功能介绍主界面键盘列表页面键盘配置&#xff08;使用双模键盘的请务必细看本说明&#xff09;功能层配置(改键)触发层配置(改FN键等触发功能)功能选择&#xff08;重要&a…