当前位置: 首页 > news >正文

做照片的网站有哪些软件seo品牌推广方法

做照片的网站有哪些软件,seo品牌推广方法,毕业设计做网站要求,个人网站 备案 广告并发访问slice 线上出现一粒多协程并发append全局slice的情况,导致内存不断翻倍,因此对slice的使用需要重新考虑。 并发读写的情况下, 可以利用锁、channel等避免竞态 问题 func TestDemo32(t *testing.T) {var wg sync.WaitGroupvar n 1…

并发访问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

http://www.ds6.com.cn/news/9344.html

相关文章:

  • 电子商务网站建设实训总结网络推广哪家做得比较好
  • 可以做网站引导页的页面电商seo
  • 网站信息系统设计中国十大教育培训机构有哪些
  • author 1 wordpress网站如何做关键词优化
  • 免费做电子邀请涵的网站网络软文广告
  • 武清区网站建设搜索引擎关键词怎么选
  • 百度云服务器搭建网站步骤天津百度网站快速优化
  • 公司网站建设需要些什么要求seo网站排名全选
  • 股票海选公司用什么网站外贸营销网站建设介绍
  • 公司做网站能够带来的好处使用软件提高百度推广排名
  • 国内新闻最新消息台湾外贸seo公司
  • 做ui要上那些网站网站流量数据分析
  • 北京网站建设哪家比较好游戏推广是什么工作
  • 潍坊公司网站模板建站东莞seo外包公司
  • 网站建设高级开发语言百度排名工具
  • 小程序制作平台价格厦门seo外包服务
  • 网站建设中模版vivo应用商店
  • 国内做新闻比较好的网站seo和网络推广有什么区别
  • 体育西网站开发方案网络营销专业课程
  • 网站建设 网站开发互联网产品营销策划方案
  • 《动态网站建设》在线测试公司做个网站多少钱
  • 西宁网站建设官网爱链在线
  • 公司网站宣传自己做的灯展视频推广平台
  • 宜昌最权威网站建设公司天津提升专业关键词排名
  • 环保网站 中企动力建设网络推广策划方案模板
  • 网站建设平台网络维护公司
  • 公司做网站需要几个人bt兔子磁力天堂
  • 建材企业网站模板佛山本地网站建设
  • 产品介绍网站htmlseo对网店推广的作用
  • wordpress建站平台百度小说排行榜总榜