阅读golang sync.Once文档

This commit is contained in:
asahi
2025-01-11 16:17:27 +08:00
parent 8a0d036a14
commit 26c14bbc9d

View File

@@ -1,3 +1,46 @@
- [Golang](#golang)
- [Get Started](#get-started)
- [Enable dependency tracking](#enable-dependency-tracking)
- [go mod init](#go-mod-init)
- [go mod tidy](#go-mod-tidy)
- [multi-module workspace](#multi-module-workspace)
- [go work init](#go-work-init)
- [go work use](#go-work-use)
- [Gin框架构建restful api](#gin框架构建restful-api)
- [向response中写入返回数据](#向response中写入返回数据)
- [解析request中的数据](#解析request中的数据)
- [将请求的endpoint注册到server中](#将请求的endpoint注册到server中)
- [golang generic](#golang-generic)
- [不使用泛型的代码编写](#不使用泛型的代码编写)
- [使用泛型的代码编写](#使用泛型的代码编写)
- [comparable](#comparable)
- [泛型方法调用](#泛型方法调用)
- [type constraint](#type-constraint)
- [Fuzzing](#fuzzing)
- [unit test编写](#unit-test编写)
- [fuzz test编写](#fuzz-test编写)
- [执行fuzz test](#执行fuzz-test)
- [sync.Pool](#syncpool)
- [sync.Pool使用示例](#syncpool使用示例)
- [Pool和垃圾回收](#pool和垃圾回收)
- [poolCleanup](#poolcleanup)
- [allPools \& oldPools](#allpools--oldpools)
- [Proc Pining](#proc-pining)
- [per-P](#per-p)
- [local \& localSize](#local--localsize)
- [PinSlow](#pinslow)
- [Pool Local](#pool-local)
- [pool的Put/Get](#pool的putget)
- [Put](#put)
- [Get](#get)
- [slow path](#slow-path)
- [Sync.once](#synconce)
- [use case](#use-case)
- [syntax](#syntax)
- [iota](#iota)
# Golang
## Get Started
### Enable dependency tracking
@@ -310,8 +353,7 @@ ok git.kazusa.red/asahi/fuzz-demo 10.360s
> #### new interesting
> `new interesting`指会扩充code coverage的用例输入在fuzz test刚开始时new interesting数量通常会因发现新的代码路径快速增加然后会随着时间的推移逐渐减少
## Go Sync
### sync.Pool
## sync.Pool
`sync.Pool`为golang标准库中的实现用于降低allocation和减少垃圾回收。
### sync.Pool使用示例
@@ -708,6 +750,61 @@ func (p *Pool) getSlow(pid int) any {
- 如果所有victim中的poolLocal对象都返回为空那么会将victim中`p.victimSize`标识为空后续再次执行slow path时如果感知到victimSize为空那么便不会再次查找victim
## Sync.once
sync.Once是golang中提供的工具包确保指定的代码块在并发环境下只会被执行一次。
sync.Once为struct其中只包含一个方法`Do(f func())`。sync.Once保证指定方法只会被执行一次即使在多routine环境下被调用了多次。`并且sync.Once方法是线程安全的`
### use case
sync.Once的用例如下
- 对共享的资源进行初始化
- 设置单例
- 执行只需要运行一次的高开销计算
- 导入配置文件
sync.Once的使用示例如下
```go
var instance *singleton
var once sync.Once
func getInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}
```
sync.Once实现逻辑如下
```go
type Once struct {
// done indicates whether the action has been performed.
// It is first in the struct because it is used in the hot path.
// The hot path is inlined at every call site.
// Placing done first allows more compact instructions on some architectures (amd64/386),
// and fewer instructions (to calculate offset) on other architectures.
done atomic.Uint32
m Mutex
}
func (o *Once) Do(f func()) {
if o.done.Load() == 0 {
// Outlined slow-path to allow inlining of the fast-path.
o.doSlow(f)
}
}
func (o *Once) doSlow(f func()) {
o.m.Lock()
defer o.m.Unlock()
if o.done.Load() == 0 {
defer o.done.Store(1)
f()
}
}
```
## syntax
### iota
`iota`关键字代表连续的整数变量,`0, 1, 2`,每当`const`关键字出现时其重置为0