值得一看
广告
彩虹云商城
广告

热门广告位

如何在Golang中使用sync实现并发安全

Go语言中通过sync包实现并发安全,1. 使用sync.Mutex保护共享变量,如计数器示例防止数据竞争;2. 使用sync.RWMutex提升读多写少场景性能,允许多个读操作并发;3. 使用sync.Once确保初始化操作仅执行一次,适用于单例模式;4. 使用sync.WaitGroup等待所有goroutine完成,常用于任务协调。合理使用这些原语可避免竞态条件,提升程序稳定性与效率。

如何在golang中使用sync实现并发安全

在Go语言中,并发安全通常通过 sync 包来实现。该包提供了多种同步原语,帮助开发者在多个goroutine访问共享资源时避免竞态条件。以下是几种常见的使用方式和场景。

1. 使用 sync.Mutex 保护共享变量

当多个 goroutine 同时读写同一个变量时,需要使用互斥锁(Mutex)来确保同一时间只有一个 goroutine 能访问该资源。

示例:并发安全的计数器

立即学习“go语言免费学习笔记(深入)”;

package main
<p>import (
"fmt"
"sync"
)</p><p>var counter int
var mu sync.Mutex</p><p>func increment(wg *sync.WaitGroup) {
defer wg.Done()
mu.Lock()
counter++
mu.Unlock()
}</p><p>func main() {
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(1)
go increment(&wg)
}
wg.Wait()
fmt.Println("Counter:", counter) // 输出: Counter: 1000
}

说明:每次对 counter 的修改都包裹在 mu.Lock()mu.Unlock() 中,防止数据竞争。

2. 使用 sync.RWMutex 提高读性能

如果共享资源以读操作为主,可以使用读写锁 RWMutex。它允许多个读操作并发执行,但写操作独占锁。

示例:线程安全的配置存储

package main
<p>import (
"fmt"
"sync"
"time"
)</p><p>var config = make(map[string]string)
var rwmu sync.RWMutex</p><p>func readConfig(key string) string {
rwmu.RLock()
value := config[key]
rwmu.RUnlock()
return value
}</p><p>func writeConfig(key, value string) {
rwmu.Lock()
config[key] = value
rwmu.Unlock()
}</p><p>func main() {
go func() {
for i := 0; i < 10; i++ {
writeConfig("version", fmt.Sprintf("v%d", i))
time.Sleep(100 * time.Millisecond)
}
}()</p><pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;">var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 5; j++ {
v := readConfig("version")
fmt.Println("Read:", v)
time.Sleep(50 * time.Millisecond)
}
}()
}
wg.Wait()

}

说明:RLock/RUnlock 用于读操作,Lock/Unlock 用于写操作,提升并发读性能。

如知AI笔记

如知AI笔记

如知笔记——支持markdown的在线笔记,支持ai智能写作、AI搜索,支持DeepseekR1满血大模型

如知AI笔记27

查看详情
如知AI笔记

3. 使用 sync.Once 实现单次初始化

某些初始化操作只需执行一次,例如加载配置、初始化连接池等。sync.Once 可保证函数只运行一次,即使被多个goroutine调用。

示例:单例模式初始化

package main
<p>import (
"fmt"
"sync"
)</p><p>var instance *Service
var once sync.Once</p><p>type Service struct {
Data string
}</p><p>func GetService() *Service {
once.Do(func() {
instance = &Service{Data: "Initialized"}
fmt.Println("Service initialized")
})
return instance
}</p><p>func main() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
s := GetService()
fmt.Println(s.Data)
}()
}
wg.Wait()
}

输出中“Service initialized”只会打印一次。

4. 使用 sync.WaitGroup 等待 goroutine 完成

WaitGroup 用于主线程等待一组goroutine执行完毕,常用于并发任务协调。

示例:并发下载多个资源

package main
<p>import (
"fmt"
"sync"
)</p><p>func download(url string, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println("Downloading from", url)
// 模拟耗时操作
// time.Sleep(time.Second)
}</p><p>func main() {
urls := []string{
"<a href="https://www.php.cn/link/0a16224c296f72af9037875a027f94a6">https://www.php.cn/link/0a16224c296f72af9037875a027f94a6</a>",
"<a href="https://www.php.cn/link/6f942b9867c5426a14f5841ece172b18">https://www.php.cn/link/6f942b9867c5426a14f5841ece172b18</a>",
"<a href="https://www.php.cn/link/909c71100210781d37a568c5fc14e627">https://www.php.cn/link/909c71100210781d37a568c5fc14e627</a>",
}</p><pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;">var wg sync.WaitGroup
for _, url := range urls {
wg.Add(1)
go download(url, &wg)
}
wg.Wait()
fmt.Println("All downloads completed")

}

说明:每个 goroutine 开始前调用 Add(1),结束后调用 Done(),主线程通过 Wait() 阻塞直到全部完成。

基本上就这些常见用法。合理使用 sync 包中的工具,能有效避免数据竞争,实现安全高效的并发编程。注意不要过度加锁,避免死锁或性能下降。

相关标签:

go golang go语言 工具 ai 并发编程 golang 线程 主线程 Go语言 并发

大家都在看:

使用 Go 的 net/http 包服务 PHP 文件
Go Datastore Put 操作中的“无效实体类型”错误解析
Go语言并发执行外部命令:构建高效协程池的最佳实践
Go语言中带有互斥锁的结构体如何安全地实现JSON序列化
Go语言中向已关闭的Tar归档文件追加内容的实现方法
温馨提示: 本文最后更新于2025-10-24 22:28:57,某些文章具有时效性,若有错误或已失效,请在下方留言或联系在线客服
文章版权声明 1 本网站名称: 创客网
2 本站永久网址:https://new.ie310.com
1 本文采用非商业性使用-相同方式共享 4.0 国际许可协议[CC BY-NC-SA]进行授权
2 本站所有内容仅供参考,分享出来是为了可以给大家提供新的思路。
3 互联网转载资源会有一些其他联系方式,请大家不要盲目相信,被骗本站概不负责!
4 本网站只做项目揭秘,无法一对一教学指导,每篇文章内都含项目全套的教程讲解,请仔细阅读。
5 本站分享的所有平台仅供展示,本站不对平台真实性负责,站长建议大家自己根据项目关键词自己选择平台。
6 因为文章发布时间和您阅读文章时间存在时间差,所以有些项目红利期可能已经过了,能不能赚钱需要自己判断。
7 本网站仅做资源分享,不做任何收益保障,创业公司上收费几百上千的项目我免费分享出来的,希望大家可以认真学习。
8 本站所有资料均来自互联网公开分享,并不代表本站立场,如不慎侵犯到您的版权利益,请联系79283999@qq.com删除。

本站资料仅供学习交流使用请勿商业运营,严禁从事违法,侵权等任何非法活动,否则后果自负!
THE END
喜欢就支持一下吧
点赞5赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容