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

wordpress微商模板360seo

wordpress微商模板,360seo,秦皇岛网站推广价钱,logo设计说明并发编程-Sync包 sync.WaitGroup 在代码中生硬的使用time.Sleep肯定是不合适的,Go语言中可以使用sync.WaitGroup来实现并发任务的同步。 sync.WaitGroup有以下几个方法: 方法名功能(wg * WaitGroup) Add(delta int)计数器delta(wg *WaitGroup) Done()…

并发编程-Sync包

sync.WaitGroup

在代码中生硬的使用time.Sleep肯定是不合适的,Go语言中可以使用sync.WaitGroup来实现并发任务的同步。 sync.WaitGroup有以下几个方法:

方法名功能
(wg * WaitGroup) Add(delta int)计数器+delta
(wg *WaitGroup) Done()计数器-1
(wg *WaitGroup) Wait()阻塞直到计数器变为0

sync.WaitGroup内部维护着一个计数器,计数器的值可以增加和减少。例如当我们启动了N 个并发任务时,就将计数器值增加N。每个任务完成时通过调用Done()方法将计数器减1。通过调用Wait()来等待并发任务执行完,当计数器值为0时,表示所有并发任务已经完成。

我们利用sync.WaitGroup将上面的代码优化一下:

var wg sync.WaitGroupfunc hello() {defer wg.Done()fmt.Println("Hello Goroutine!")
}
func main() {wg.Add(1)go hello() // 启动另外一个goroutine去执行hello函数fmt.Println("main goroutine done!")wg.Wait()
}

需要注意sync.WaitGroup是一个结构体,传递的时候要传递指针。

sync.Once

sync.Once 是 Go 语言 sync 包提供的一个同步原语,用于确保某个操作只执行一次,无论它被调用多少次或有多少个 Goroutine 同时尝试执行它。

它的主要用途包括:

1.延迟初始化 (Lazy Initialization):当你想在资源第一次被需要时才进行初始化,而不是在程序启动时就初始化,sync.Once 可以确保初始化只发生一次,从而避免重复初始化的开销。

import ("fmt""sync""time"
)var once sync.Once
var expensiveResource stringfunc getExpensiveResource() string {once.Do(func() {fmt.Println("正在初始化昂贵资源......")time.Sleep(100 * time.Millisecond) // 模拟初始化耗时expensiveResource = "这是一个昂贵的资源"})return expensiveResource
}func main() {var wg sync.WaitGroupfor i := 0; i < 5; i++ {wg.Add(1)go func() {defer wg.Done()fmt.Println(getExpensiveResource())}()}wg.Wait()fmt.Println("所有 Goroutine 已完成。")
}

在上面的例子中,"正在初始化昂贵资源..." 只会被打印一次,即使 getExpensiveResource 被多个 Goroutine 调用。

QQ_1748327479922

2.单例模式 (Singleton Pattern):确保一个类的实例只被创建一次。

package mainimport ("fmt""sync"
)type Singleton struct {Name string
}var (instance *Singletononce     sync.Once
)func GetSingletonInstance() *Singleton {once.Do(func() {fmt.Println("create Singleton instance")instance = &Singleton{Name: "my Singleton instance"}})return instance
}func main() {var wg sync.WaitGroupfor i := 0; i < 5; i++ {wg.Add(1)go func() {defer wg.Done()s := GetSingletonInstance()fmt.Println(s.Name)}()}wg.Wait()
}

QQ_1748327550850

3.包级别初始化 (Package-Level Initialization):在包加载时进行一次性设置。

sync.Once 的新特性 (Go 1.21 及更高版本)

Go 1.21 引入了 OnceFunc, OnceValue, 和 OnceValues,它们是 sync.Once 的封装,提供了更简洁的用法:

  • OnceFunc(f func()) func(): 返回一个函数,该函数只会调用 f 一次。多次调用返回的函数都会执行,但 f 只会在第一次被调用。
  • OnceValue[T any](f func() T) func() T: 返回一个函数,该函数只会调用 f 一次并缓存 f 的返回值。后续调用都会返回相同的值。
  • OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2): 类似于 OnceValue,但用于返回两个值。

示例:OnceValue

package mainimport ("fmt""sync"
)func main() {// 定义一个只计算一次并返回结果的函数getSumOnce := sync.OnceValue(func() int {sum := 0for i := 0; i < 1000; i++ {sum += i}fmt.Println("计算了一次:", sum)return sum})var wg sync.WaitGroupfor i := 0; i < 10; i++ {wg.Add(1)go func() {defer wg.Done()result := getSumOnce() // 这里开辟10个协程 执行函数,但实际只执行了一次fmt.Printf("Goroutine %d 得到结果: %d\n", i, result)}()}wg.Wait()
}

在这个例子中,getSumOnce 函数只会在第一次被调用时执行内部的求和逻辑,并打印 “计算了一次:”,之后的调用会直接返回缓存的结果。

QQ_1748327857447

重要注意事项:

  • sync.Once 实例一旦执行过其 Do 方法,就不能被重置。
  • 如果传递给 Do 方法的函数发生 panic,sync.Once 仍会认为该操作已完成,后续调用不会再次执行该函数。
  • sync.Once 不应被复制。

总而言之,sync.Once 是 Go 中一个强大且常用的同步工具,用于安全地执行一次性初始化。

sync.Map

sync.Map 是 Go 语言 sync 包提供的一个并发安全的哈希映射(map),它旨在解决 Go 内置 map 在并发访问时需要外部 sync.RWMutex 保护的性能问题,尤其是在读多写少的场景下。

Go 语言内置的 map 不是并发安全的。如果在多个 Goroutine 中同时对一个 map 进行读写操作,会导致数据竞争(data race),进而引发程序崩溃或产生不确定的行为。为了解决这个问题,通常需要使用 sync.RWMutex 来保护 map 的并发访问

var m = make(map[string]int)func get(key string) int {return m[key]
}func set(key string, value int) {m[key] = value
}func main() {wg := sync.WaitGroup{}for i := 0; i < 20; i++ {wg.Add(1)go func(n int) {key := strconv.Itoa(n)set(key, n)fmt.Printf("k=:%v,v:=%v\n", key, get(key))wg.Done()}(i)}wg.Wait()
}

QQ_1748328489525

上面的代码开启少量几个goroutine的时候可能没什么问题,当并发多了之后执行上面的代码就会报fatal error: concurrent map writes错误。

像这种场景下就需要为map加锁来保证并发的安全性了,Go语言的sync包中提供了一个开箱即用的并发安全版map–sync.Map。开箱即用表示不用像内置的map一样使用make函数初始化就能直接使用。同时sync.Map内置了诸如Store、Load、LoadOrStore、Delete、Range等操作方法

sync.Map 的常用方法:

  • Store(key, value interface{}): 将 key-value 对存储到 Map 中。

  • Load(key interface{}) (value interface{}, ok bool): 根据 key 加载值。如果 key 存在,返回 value 和 true;否则返回 nil 和 false。

  • LoadOrStore(key, value interface{}) (actual interface{}, loaded bool): 如果 key 存在,则返回其现有值和 true;否则,存储新的 key-value 对并返回 value 和 false。这是一个非常常用的方法,可以实现“如果不存在就存储,否则就加载”的逻辑。

  • Delete(key interface{}): 从 Map 中删除 key 及其对应的值。

  • Range(f func(key, value interface{}) bool): 遍历 Map 中的所有 key-value 对,对每个对调用提供的函数 f。如果 f 返回 false,则停止遍历。注意:在 Range 期间,Map 可能会被并发修改,所以遍历的结果可能不是一个完全一致的快照。

var m = sync.Map{}func main() {wg := sync.WaitGroup{}for i := 0; i < 10; i++ {wg.Add(1)go func(n int) {key := strconv.Itoa(n)m.Store(key, n)value, _ := m.Load(key)fmt.Printf("k=:%v,v:=%v\n", key, value)wg.Done()}(i)}wg.Wait()
}

QQ_1748328657099

http://www.dtcms.com/wzjs/468313.html

相关文章:

  • 杭州网站建站公司公司做网站需要多少钱
  • 做外汇上什么网站看新闻产品seo标题是什么
  • 企业网站营销案例网络营销专业怎么样
  • ftp怎么修改网站优化网络搜索引擎
  • 网站后期维护怎么做上海网络推广团队
  • 建个简单网站长尾关键词挖掘词工具
  • 网站首页权重门户网站怎么做
  • 免费的网站模板哪里有网站首页不收录
  • 三好街做网站的怎么制作一个网页
  • 专业网站建设公司地址搜索引擎有哪些好用
  • 个体工商户注册流程四川seo关键词工具
  • 全国市场主体登记注册服务网seo整站排名
  • 本网站建设服务于美国广州网站建设公司
  • 荆门做网站的公司裂变营销五种模式十六种方法
  • HTML网站页面建设重庆seo公司排名
  • 网站后端开发是什么seo自媒体培训
  • 怎么做网站的图片跳转程序员培训机构哪家好
  • 局域网内部如何做网站哪家公司做seo
  • seo整站优化外包哪家好北京seo外包 靠谱
  • 帮做装修设计的网站手机关键词排名优化
  • wordpress漂浮花瓣高明搜索seo
  • wordpress 引用页面百度的seo关键词优化怎么弄
  • 网站名词排名怎么做最近新闻摘抄50字
  • 国内外网站在线发外链工具
  • 桂林北站到桂林站多远镇江网站建设
  • 山东胜越石化工程建设有限公司网站电脑编程培训学校哪家好
  • 建设网站青岛手机网页制作
  • 目录网站做外链企业营销策划是做什么的
  • 网站建设模板制作郑州seo外包费用
  • 大型网站运营步骤郑州网站优化排名