Golang|单机并发缓存

server/2025/1/15 23:32:19/
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/server/158683.html

相关文章

日常网络小知识

日常网络小知识 IPV4 IPv4&#xff08;Internet Protocol version 4&#xff09;是最常用的互联网协议之一&#xff0c;它使用 32 位二进制数来表示一个 IP 地址&#xff0c;通常写成十进制形式&#xff0c;用点分隔四个数字&#xff0c;每个数字表示一个字节&#xff08;8位…

Deep4SNet: deep learning for fake speech classification

Deep4SNet&#xff1a;用于虚假语音分类的深度学习 摘要&#xff1a; 虚假语音是指即使通过人工智能或信号处理技术产生的语音记录。生成虚假录音的方法有"深度语音"和"模仿"。在《深沉的声音》中&#xff0c;录音听起来有点合成&#xff0c;而在《模仿》中…

力扣经典题目之55.跳跃游戏

2&#xff0c;解题思路 public class Solution {public boolean canJump(int[] nums) {int n nums.length;int rightmost 0;for (int i 0; i < n; i) {if (i < rightmost) {rightmost Math.max(rightmost, i nums[i]);if (rightmost > n - 1) {return true;}}}r…

vim基本命令(vi、工作模式、普通模式、插入模式、可视模式、命令行模式、复制、粘贴、插入、删除、查找、替换)

1. Vim的作用 1.1. 文本编辑 1.1.1. 基础文本编辑功能 Vim是一个功能强大的文本编辑器&#xff0c;它可以用来创建、修改和保存各种文本文件。无论是编写简单的文本笔记&#xff0c;还是复杂的代码文件&#xff0c;Vim都能胜任。例如&#xff0c;我们可以用它来编写Python脚…

51单片机 AT24C02(I2C总线)

存储器 随机存储 RAM 只读存储 ROM AT24C02芯片 是一种可以实现掉电不丢失的存储器&#xff0c;可用于保存单片机运行时想要永久保存的数据信息 存储材质&#xff1a;E2PROM 通讯接口&#xff1a;I2C总线 容量&#xff1a;256字节 I2C总线 一种通用的数据总线 两根通信线…

计算机视觉算法实战——视频分析(Video Analysis)

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​​​​ ​​​​​​​​​​​​ ​​​​​ 视频分析是计算机视觉中的一个重要领域&#xff0c;旨在从视频数据中提取有用的信息&…

java_mybatis_mapper_sql语句示例

需求&#xff1a; 有2张表&#xff0c;一张活动信息表(activity_info), 一张参加活动的商品表&#xff08;activity_sku&#xff09; 查询当前在活动期间的&#xff0c;且存在于我输入的商品(sku)列表中的商品(sku)的编号id 参考&#xff1a;63 尚上优选项目-平台管理端-营销…

多模态人工智能在零售业的未来:通过GPT-4 Vision和MongoDB实现智能产品发现

多模态人工智能在零售业的未来&#xff1a;通过GPT-4 Vision和MongoDB实现智能产品发现 引言 想象一下&#xff0c;顾客在购物时只需上传一张他们所期望的服装或产品的照片&#xff0c;几分钟内便能收到来自他们最喜欢的商店的个性化推荐。这就是多模态人工智能在零售领域所带…