惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

美团技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - Franky
有赞技术团队
有赞技术团队
博客园 - 司徒正美
量子位
N
News and Events Feed by Topic
T
Threatpost
Last Week in AI
Last Week in AI
D
Darknet – Hacking Tools, Hacker News & Cyber Security
酷 壳 – CoolShell
酷 壳 – CoolShell
C
CERT Recently Published Vulnerability Notes
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
I
Intezer
人人都是产品经理
人人都是产品经理
T
Tenable Blog
IT之家
IT之家
雷峰网
雷峰网
腾讯CDC
博客园 - 聂微东
V
Visual Studio Blog
S
SegmentFault 最新的问题
Scott Helme
Scott Helme
Spread Privacy
Spread Privacy
月光博客
月光博客
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
V2EX
大猫的无限游戏
大猫的无限游戏
Apple Machine Learning Research
Apple Machine Learning Research
爱范儿
爱范儿
T
Tailwind CSS Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
罗磊的独立博客
N
Netflix TechBlog - Medium
J
Java Code Geeks
宝玉的分享
宝玉的分享
F
Full Disclosure
WordPress大学
WordPress大学
A
Arctic Wolf
小众软件
小众软件
AWS News Blog
AWS News Blog
Attack and Defense Labs
Attack and Defense Labs
NISL@THU
NISL@THU
AI
AI
Hugging Face - Blog
Hugging Face - Blog
F
Fortinet All Blogs
云风的 BLOG
云风的 BLOG
N
News | PayPal Newsroom
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org

鸟窝

鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 鸟窝 LLM 究竟是如何工作的? Go 实验特性详解 amd64 微架构级别对 Go 程序性能提升多少? Loop Engineering 实践:一次批量实现 8 个 issue,完成夔牛工具的开发 Loop Engineering 实践:我把 RDMA 开发库移植到 Go 语言,花费 239 块钱 傻瓜式RDMA高性能网络开发:从零跑到 400 Gb每秒 百度物理网络监控工具开源第二弹:毫秒级监控工具 baize,让你的网络问题无处遁形 百度网络监控工具开源第三弹:lidar — 不只是 pingmesh 别只盯着gopacket了,看看这个强大的网络库 大厂的内部工具居然开源了! 一窥百度物理网络秒级监控定位的秘密 如何构建你自己的 Agent 运行时 寻找你代码中的臭味:一个让 AI 帮你嗅出架构腐化的开源 Skill 套壳不丢人!我用Go+AI搓了一个Agent统一编排框架,ClaudeCode-Codex-Pi全被我包了 告别死锁和陈旧语法、告别性能瓶颈:三个开源 Skill,新手Gopher 秒变 Go 语言大神 SPEC和PRD的区别 SPEC和方案设计有什么区别 从需求到上线,让 AI 管理你的整个研发流程! antigravity-cli 使用 CLIProxyAPI, 让最新的 Codex 能够支持国内的各大模型 Clawpatch + codex-review:AI 代码审查工具链的正确打开方式 拆解Manus:沙盒架构深度解析 40+ Claude Code Tips: From Basics to Advanced Ralph 实验:构建 SQLite UI 了解 Manus Sandbox - 您的云计算机 Notex:一个开源 NotebookLM 替代方案的实现 拆解Manus:真正有用的深度报告的生成 Claude Code 使用 我给每个模型服务商『捐』了10块钱,只为了... Go之禅 - 基于Rob Pike思想的Go语言哲学 Codex CLI vs Gemini CLI vs Claude Code:谁是最佳选择? goskills:Claude Skills 功能强大,为我所用 一行代码使用 Claude Skill 和 deepseek langchain + MCP:如虎添翼 Linux 中网络包的一生 godotenv 库介绍 Codex CLI vs Gemini CLI vs Claude Code: Which is the Best? 使用Linux 30年了,我都不知道 ping 8.8 还能这么用? 从 AI 哪里挣钱? deepseek-v3.2-exp的闪电索引器
Go sync 包近两年发展综述
by smallnest · 2025-10-01 · via 鸟窝

Go 语言的 sync 包是其并发编程模型的基石,提供了实现同步和并发控制的关键原语。在过去的两年里(大约从 Go 1.19 到 1.25),sync 包及其子包 sync/atomic 经历了一系列重要的演进。这些变化不仅包括新功能的增加,还涉及性能优化、内部实现的重构以及开发者体验的显著提升。

本文基于 Go 语言官方仓库的 Git 提交历史,对 sync 包近两年的主要变化进行总结。

1. 新增 API 与功能增强

为了简化常见的并发模式,sync 包引入了一些备受期待的新 API。

sync.WaitGroup.Go

Go 1.25 引入了 WaitGroup.Go 方法,极大地简化了在 WaitGroup 中启动 goroutine 的代码。

旧模式:

1

2

3

4

5

wg.Add(1)

go func() {

defer wg.Done()

}()

新模式:

1

2

3

wg.Go(func() {

})

这个辅助方法不仅减少了样板代码,还通过内置的 defer wg.Done() 调用避免了忘记调用 Done() 的常见错误。

代码示例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

package main

import (

"fmt"

"sync"

"time"

)

func main() {

var wg sync.WaitGroup

urls := []string{

"http://example.com",

"http://example.org",

"http://example.net",

}

for _, url := range urls {

wg.Go(func() {

fmt.Printf("Fetching %s\n", url)

time.Sleep(100 * time.Millisecond)

fmt.Printf("Fetched %s\n", url)

})

}

wg.Wait()

fmt.Println("All fetches completed.")

}

sync.Map.Clearsync.Map.Swap

sync.Map 也获得了一些实用的新方法:

  • Clear(): 用于一次性删除 Map 中的所有键值对,提供了一种高效清空 Map 的标准方式 (Go 1.23.0)。
  • Swap(): 原子性地交换一个键的新旧值 (Go 1.20)。
  • CompareAndSwap() / CompareAndDelete(): 提供了更精细的原子操作,允许用户基于旧值进行条件交换或删除 (Go 1.20)。

代码示例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

package main

import (

"fmt"

"sync"

)

func main() {

var m sync.Map

m.Store("config", "v1")

m.Store("feature_flag", "off")

oldValue, loaded := m.Swap("config", "v2")

if loaded {

fmt.Printf("Swapped 'config'. Old value was: %s\n", oldValue)

}

currentValue, _ := m.Load("config")

fmt.Printf("Current value of 'config' is: %s\n", currentValue)

fmt.Println("\nClearing the map...")

m.Clear()

m.Range(func(key, value interface{}) bool {

fmt.Println("This should not be printed.")

return true

})

fmt.Println("Map is empty.")

}

sync.Once 系列函数的演进

Go 1.21.0 引入的 OnceFunc, OnceValue, OnceValues 在后续版本中得到了优化,例如减少了堆内存分配,使其在需要延迟初始化或缓存计算结果的场景下更高效。func

  • OnceFunc(f func()) func():将一个无参数无返回值的函数包装成只执行一次的函数。
  • func OnceValue[T any](f func() T) func() T: 将一个无参数但有单个返回值的函数包装成只执行一次的函数,后续调用返回缓存的结果。
  • func OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2): 将一个无参数但有两个返回值的函数包装成只执行一次的函数,后续调用返回缓存的结果。

代码示例 (OnceValue)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

package main

import (

"fmt"

"sync"

)

func main() {

once := sync.OnceValue(func() int {

sum := 0

for i := 0; i < 1000; i++ {

sum += i

}

fmt.Println("Computed once:", sum)

return sum

})

done := make(chan bool)

for i := 0; i < 10; i++ {

go func() {

const want = 499500

got := once()

if got != want {

fmt.Println("want", want, "got", got)

}

done <- true

}()

}

for i := 0; i < 10; i++ {

<-done

}

}

2. 性能优化与内部实现重构

sync 包的性能至关重要。近期的更新在多个方面对其进行了优化。

sync.Map 的新实现

sync.Map 的内部实现经历了一次重大变更,引入了基于哈希分片三角树(HashTrieMap)的新设计 (Go 1.24)。但这类探索表明了社区在持续寻求提升 sync.Map 在不同并发场景下性能的努力。

sync.Mutex 内部重构

Mutex 在Go1.24.0增加了一个基于HashTrieMap的实现。在Go1.26.0中应该会移除旧的sync.Mutex实现, sync.Map将默认采用HashTrieMap的实现。

https://github.com/golang/go/issues/70683

sync.Once 的原子操作优化

Once.done 字段的实现从 atomic.Uint32 切换到atomic.Bool (Go 1.25)。这不仅提升了代码的可读性和类型安全性,也代表了用现代原子类型替代旧有模式的趋势。

3. 代码正确性与开发者体验

为帮助开发者编写更健壮的并发代码,sync 包在文档和静态分析方面做了大量改进。

noCopy 哨兵的引入

Mutex, RWMutex, WaitGroup, Cond, 和 Map 等核心类型都加入了 noCopy 字段。这是一个特殊的非导出字段,可以被 go vet 工具识别。当开发者无意中复制了这些包含内部状态的同步原语时,go vet 会发出警告,从而在编译前发现潜在的并发 bug。

代码示例 (错误用法):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

package main

import "sync"

type Counter struct {

sync.Mutex

count int

}

func (c Counter) Inc() {

c.Lock()

c.count++

c.Unlock()

}

func main() {

var c Counter

c.Inc()

}

文档的持续改进

大量的提交都致力于改进和澄清文档,包括:

  • 明确指出 RWMutex 的读锁和写锁不能相互升级或降级。
  • 详细描述了 MapRangeDelete 等方法在并发访问下的行为和内存模型保证。
  • Cond.Wait 的行为提供了更清晰的说明。
  • 在包文档中直接链接到 Go 内存模型,强调其重要性。

4. sync/atomic 的现代化

作为 sync 的底层支撑,sync/atomic 包在 Go 1.19 中引入了基于泛型的类型安全原子类型(如 atomic.Int64, atomic.Pointer[T], atomic.Bool 等)。近两年的变化主要体现在:

  • 鼓励使用新类型:在 sync 包内部,旧的函数式原子操作(如 atomic.LoadUint32)正逐渐被新的类型化方法(如 myAtomicBool.Load())所取代。
  • API 完善:增加了 And/Or 等新的原子位操作函数,并对文档进行了补充,以指导用户从旧 API 过渡到新 API。

总结

过去两年,Go 的 sync 包在保持 API 稳定的同时,向着更易用、更安全、更高性能的方向稳步发展。通过引入 WaitGroup.Go 等便捷的辅助函数,开发者可以编写更简洁的并发代码。noCopy 哨兵和持续完善的文档则提高了代码的健壮性。底层的性能优化和实现重构,确保了 Go 的并发原语能够适应不断增长的性能需求。这些变化共同巩固了 Go 作为一门现代并发语言的地位。