go的slice学习
并发访问slice
线上出现一粒多协程并发append全局slice的情况,导致内存不断翻倍,因此对slice的使用需要重新考虑。
并发读写的情况下, 可以利用锁、channel等避免竞态
问题
func TestDemo32(t *testing.T) {var wg sync.WaitGroupvar n = 100s := make([]int, 0, 200)hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s))fmt.Printf("Data addr: %d\n", hdr.Data)fmt.Printf("Data cap: %d\n", hdr.Cap)fmt.Printf("Data len: %d\n", hdr.Len)wg.Add(n)for i := 1; i <= n; i++ {go func(v int) {defer wg.Done()s = append(s, v)}(i)}wg.Wait()hdr = (*reflect.SliceHeader)(unsafe.Pointer(&s))fmt.Printf("Data addr: %d\n", hdr.Data)fmt.Printf("Data cap: %d\n", hdr.Cap)fmt.Printf("Data len: %d\n", hdr.Len)fmt.Println(jsonx.ToString(s))// Data addr: 824645965056// Data cap: 200// Data len: 0// Data addr: 824645965056// Data cap: 200// Data len: 96
}func TestDemo33(t *testing.T) {var wg sync.WaitGroupvar n = 500s := make([]int, 0, 10)hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s))fmt.Printf("Data addr: %d\n", hdr.Data)fmt.Printf("Data cap: %d\n", hdr.Cap)fmt.Printf("Data len: %d\n", hdr.Len)wg.Add(n)for i := 1; i <= n; i++ {go func(v int) {defer wg.Done()s = append(s, v)}(i)}wg.Wait()hdr = (*reflect.SliceHeader)(unsafe.Pointer(&s))fmt.Printf("Data addr: %d\n", hdr.Data)fmt.Printf("Data cap: %d\n", hdr.Cap)fmt.Printf("Data len: %d\n", hdr.Len)fmt.Println(jsonx.ToString(s))// Data addr: 824635459136// Data cap: 10// Data len: 0// Data addr: 824665328128// Data cap: 672// Data len: 453
}
Go语言中的slice是一种引用类型,它本身不保存任何元素,只是对数组的引用。
append操作的主要功能是向slice添加元素。
如果slice的底层数组容量足够,就直接添加;如果不够,就会先分配新的底层数组,然后将原有的元素和新添加的元素一起拷贝到新数组,在这个过程中,原有的底层数组会被垃圾回收。
当底层数组的容量不足以容纳新的元素时,就会产生新的底层数组
此时原有的slice和返回的新的slice,其底层数组是不同的。
这也是为什么在使用append时,总是习惯性地将结果再次赋值给原slice。
方案一 channel
func TestDemo(t *testing.T) {// 无缓冲,发送侧有数据,接收侧才执行// 用于做同步c := make(chan struct{})// new 了该 job 后,该 job 就开始准备从 channel 接收数据s := NewScheduleJob(n, func() { c <- struct{}{} })// 并发发送数据到channelvar wg sync.WaitGroupvar n = 1000wg.Add(n)for i := 0; i < n; i++ {go func(v int) {defer wg.Done()s.AddData(v)}(i)}// 等待上述多个协程将数据存入slicewg.Wait()// 发送完之后关闭channels.Close()// 阻塞在这里是等待NewScheduleJob执行结束<-c// 最终实现读写一致fmt.Println(len(s.data))
}type ServiceData struct {ch chan int // 用来同步的channeldata []int // 存储数据的slice
}// Schedule 从 channel 接收数据串行存入slice,直到ch关闭
func (s *ServiceData) Schedule() {for i := range s.ch {s.data = append(s.data, i)}
}// Close 关闭channel
func (s *ServiceData) Close() {close(s.ch)
}// AddData 发送数据到 channel
func (s *ServiceData) AddData(v int) {s.ch <- v
}func NewScheduleJob(size int, done func()) *ServiceData {s := &ServiceData{ch: make(chan int, size),data: make([]int, 0),}go func() {// 并发地 append 数据到 slice// Schedule 从 channel 接收数据串行存入slice,直到ch关闭s.Schedule()// 通知主协程继续执行done()}()return s
}
优点:逻辑复杂,适用于高并发场景
方案二 - 锁
func main() {slc := make([]int, 0, 1000)var wg sync.WaitGroupvar lock sync.Mutexfor i := 0; i < 1000; i++ {wg.Add(1)go func(a int) {defer wg.Done()lock.Lock()defer lock.Unlock()slc = append(slc, a)}(i)}wg.Wait()fmt.Println(len(slc))
}
优点:锁的逻辑重,适用于对性能要求不高的场景
学习文档
https://juejin.cn/post/6844904134592692231
相关文章:
go的slice学习
并发访问slice 线上出现一粒多协程并发append全局slice的情况,导致内存不断翻倍,因此对slice的使用需要重新考虑。 并发读写的情况下, 可以利用锁、channel等避免竞态 问题 func TestDemo32(t *testing.T) {var wg sync.WaitGroupvar n 1…...

软件设计师17--磁盘管理
软件设计师17--磁盘管理 考点1:存储管理 - 磁盘管理调度算法磁盘调度 - FCFS磁盘调度 - SSTF例题: 考点1:存储管理 - 磁盘管理 存取时间寻道时间等待时间,训导时间是指磁头移动到磁道所需的时间;等待时间为等待读写的扇…...

学点Java打小工——Day2Day3一点作业
1 猜数字(10次机会) 随机生成[1,1000]的一个数,输入你猜的数程序会给出反馈,直到猜对或次数用尽(10次)。 //猜数字 10次机会Testpublic void guessNumber() {Random random new Random();// [0, 1000) 1// [1, 1000]int num ra…...

【话题】2024年AI辅助研发趋势,有那些应用领域
大家好,我是全栈小5,欢迎阅读文章! 此篇是【话题达人】系列文章,这一次的话题是《2024年AI辅助研发趋势》 目录 背景概念实践医药领域汽车设计领域展望未来文章推荐 背景 随着人工智能技术的持续发展与突破,2024年AI辅…...
蓝桥杯——数组切分
数组切分 题目分析 这里要搞清楚一个点就是满足区间内数字是连续数字的区间有什么样的特点,既然数字连续重新排列后的数字为n,n1,n2,n3,n4,…nlen,则最大数字和最小数字之差恰好是区间长度减1,即nlen-nlen,同样因为下标也是连续…...

【机器学习】进阶学习:详细解析Sklearn中的MinMaxScaler---原理、应用、源码与注意事项
【机器学习】进阶学习:详细解析Sklearn中的MinMaxScaler—原理、应用、源码与注意事项 这篇文章的质量分达到了97分,虽然满分是100分,但已经相当接近完美了。请您耐心阅读,我相信您一定能从中获得不少宝贵的收获和启发~ …...

数据库是什么?数据库连接、管理与分析工具推荐
一、数据库是什么? 数据库是一种结构化的数据存储系统,用于有效地组织、存储和管理大量的数据。它是一个集中化的数据存储库,通常由一个或多个数据表组成,每个数据表包含多个行和列,用于存储特定类型的数据。数据表中…...

【C#算法实现】可见的山峰对数量
文章目录 前言一、题目要求二、算法设计及代码实现2.1 算法思想2.2 代码实现 前言 本文是【程序员代码面试指南(第二版)学习笔记】C#版算法实现系列之一,用C#实现了《程序员代码面试指南》(第二版)栈和队列中的可见的…...

Selenium 隐藏浏览器指纹特征的几种方式
文章转载于:https://mp.weixin.qq.com/s/sXRXwMDqekUHfU2SnL-PYg 我们使用 Selenium 对网页进行爬虫时,如果不做任何处理直接进行爬取,会导致很多特征是暴露的 对一些做了反爬的网站,做了特征检测,用来阻止一些恶意爬虫…...
k8s发布nacos-server,nodeport配置注意事项
k8s发布nacos-server注册不上问题 问题描述:分析过程: 问题描述: k8s发布nacos-server做服务公用使用,nodeport暴漏服务给客户端注册, nacos:端口 8848:30601 9848:30701 分析过程:…...

伪分布式Spark集群搭建
一、软件环境 软 件 版 本 安 装 包 VMware虚拟机 16 VMware-workstation-full-16.2.2-19200509.exe SSH连接工具 FinalShell Linux OS CentOS7.5 CentOS-7.5-x86_64-DVD-1804.iso JDK 1.8 jdk-8u161-linux-x64.tar.gz Spark 3.2.1 spark-3.2.1-bin-…...

Android 监听卫星导航系统状态及卫星测量数据变化
源码 package com.android.circlescalebar;import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.Manifest; import android.conte…...

鸿蒙培训开发:就业市场的新热点~
金三银四在即,随着春节假期结束,各行各业纷纷复工复产,2024年的春季招聘市场也迎来了火爆的局面。最近发布的《2024年春招市场行情周报(第一期)》显示,尽管整体就业市场仍处于人才饱和状态,但华…...

【C++】string的底层剖析以及模拟实现
一、字符串类的认识 C语言中,字符串是以\0结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理&a…...

Unity的PICO项目基础环境搭建笔记(调试与构建应用篇)
文章目录 前言一、为设备开启开发者模式1、开启PICO VR一体机。前往设置>通用>关于本机>软件版本号2、一直点击 软件版本号 ,直到出现 开发者 选项3、进入 开发者模式,打开 USB调试,选择 文件传输 二、实时预览应用场景1、下载PC端的…...

电脑远程桌面选项变成灰色没办法勾选怎么办?
有些人在使用Windows系统自带的远程桌面工具时,会发现系统属性远程桌面选项卡中勾选启用“允许远程连接到此计算机”。 导致此问题出现的原因主要是由于组策略或者注册表设置错误造成的。 修复远程桌面选项变灰的两种方法! 方法一:设置本地组…...

2024.3.14
1.成员函数版本实现算术运算符的重载,全局函数版本实现算术运算符的重载 #include <iostream>using namespace std;class Room {friend const Room operator-(const Room &a,const Room &b); private:string a;int b; public:Room(){}Room(string a,int b):a(a)…...

chatGPT的耳朵!OpenAI的开源语音识别AI:Whisper !
语音识别是通用人工智能的重要一环!可以说是AI的耳朵! 它可以让机器理解人类的语音,并将其转换为文本或其他形式的输出。 语音识别的应用场景非常广泛,比如智能助理、语音搜索、语音翻译、语音输入等等。 然而,语音…...

C语言冒泡排序
冒泡排序是一种简单的排序算法,通过重复遍历要排序的数列,依次比较两个相邻的元素,如果它们的顺序错误则交换它们。这个过程会重复进行,直到没有相邻的元素需要交换,也就是数列已经排序完成。 冒泡排序的名字来源于其工…...
vue2 elementui 封装一个动态表单复杂组件
封装一个动态表单组件在 Vue 2 和 Element UI 中需要考虑到表单字段的动态添加、删除以及验证等复杂功能。下面是一个简单的例子,展示如何创建一个可以动态添加和删除字段的表单组件。 首先,你需要安装并引入 Element UI: bash 复制 npm in…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...
算法刷题-回溯
今天给大家分享的还是一道关于dfs回溯的问题,对于这类问题大家还是要多刷和总结,总体难度还是偏大。 对于回溯问题有几个关键点: 1.首先对于这类回溯可以节点可以随机选择的问题,要做mian函数中循环调用dfs(i&#x…...

OpenHarmony标准系统-HDF框架之I2C驱动开发
文章目录 引言I2C基础知识概念和特性协议,四种信号组合 I2C调试手段硬件软件 HDF框架下的I2C设备驱动案例描述驱动Dispatch驱动读写 总结 引言 I2C基础知识 概念和特性 集成电路总线,由串网12C(1C、12C、Inter-Integrated Circuit BUS)行数据线SDA和串…...

【笔记】结合 Conda任意创建和配置不同 Python 版本的双轨隔离的 Poetry 虚拟环境
如何结合 Conda 任意创建和配置不同 Python 版本的双轨隔离的Poetry 虚拟环境? 在 Python 开发中,为不同项目配置独立且适配的虚拟环境至关重要。结合 Conda 和 Poetry 工具,能高效创建不同 Python 版本的 Poetry 虚拟环境,接下来…...