Golang读写锁
之前写过关于互斥锁的内容, Golang互斥锁-Mutex 日期: 2022-12-27 标签: #golang #锁 #源码解析 互斥锁结构 // A Mutex is a mutual exclusion lock. // The zero value for a Mutex is an unlocked mutex. // // A Mutex must not be copied after first use. type Mutex struct { state int32 sema uint32 } state表示当前互斥锁的状态, sema是用于控制锁状态的信号量 在默认情况下,互斥锁的所有状态位都是 0,int32 中的不同位分别表示了不同的状态: mutexLocked — 表示互斥锁的锁定状态; mutexWoken — 唤醒模式,此时释放锁的g不会唤醒休眠的g; mutexStarving — 当前的互斥锁进入饥饿状态; waitersCount — 当前互斥锁上等待的 Goroutine 个数; 正常模式和饥饿模式的区别: 在正常模式下,锁的等待者会按照先进先出的顺序获取锁。但是刚被唤起的 Goroutine 与新创建的 Goroutine 竞争时,大概率会获取不到锁,为了减少这种情况的出现,一旦 Goroutine 超过 1ms 没有获取到锁,它就会将当前互斥锁切换饥饿模式,防止部分 Goroutine 被『饿死』。 ...... 互斥锁是最基础的锁,你可以在任何需要锁的场景使用它,但是它不是万能的,在某些特定场景下,我们可以用其他的锁来获得更好的性能,例如读多写少的场景,就更适合读写锁,这也是这篇文章的主题。 ...
Golang互斥锁-Mutex
互斥锁结构 // A Mutex is a mutual exclusion lock. // The zero value for a Mutex is an unlocked mutex. // // A Mutex must not be copied after first use. type Mutex struct { state int32 sema uint32 } state表示当前互斥锁的状态, sema是用于控制锁状态的信号量 在默认情况下,互斥锁的所有状态位都是 0,int32 中的不同位分别表示了不同的状态: mutexLocked — 表示互斥锁的锁定状态; mutexWoken — 唤醒模式,此时释放锁的g不会唤醒休眠的g; mutexStarving — 当前的互斥锁进入饥饿状态; waitersCount — 当前互斥锁上等待的 Goroutine 个数; 正常模式和饥饿模式的区别: 在正常模式下,锁的等待者会按照先进先出的顺序获取锁。但是刚被唤起的 Goroutine 与新创建的 Goroutine 竞争时,大概率会获取不到锁,为了减少这种情况的出现,一旦 Goroutine 超过 1ms 没有获取到锁,它就会将当前互斥锁切换饥饿模式,防止部分 Goroutine 被『饿死』。 ...
Wire 依赖注入
用法 一般会在一个名为wire.go的文件里提供需要自动注入的函数,在开头添加好tag,在函数中使用wire.Build方法,并提供创建依赖的方法,多个依赖可以组装为一个Set。 示例 // +build wireinject // tag不能忘 var ormSet = wire.NewSet(mysql.Newengine) var DataSourceSet = wire.NewSet(ormSet, japi.GetClient, cache.NewRedisCache) func InitAuthorRepo() AuthorRepoInterface { wire.Build( NewAuthorRepo, // 可以用这种方式替代New函数,特别是New的参数比较多时,*表示对结构体的全部字段进行生成 // wire.Struct(new(authorRepo), "*"), // 如果NewAuthorRepo的返回值不是显示声明AuthorRepoInterface,wire会提示无AuthorRepoInterface的provider // 此时就需要下面的语句进行绑定 // wire.Bind(new(AuthorRepoInterface), new(*authorRepo)), repo.DataSourceSet, ) return nil } 特性 wire.Struct type App struct { Foo *Foo Bar *Bar NoInject int `wire:"-"` } 该方法可以代替New函数,特别是New函数参数较多,不太好写的时候。 wire.Struct(new(App),"Foo","Bar")生成指定的字段。 wire.Struct(new(App), "*")表示结构体的全部字段都自动生成。 若是有某些字段不想在*时生成,可以给它添加tag。 wire.Bind wire.Bind(new(AuthorRepoInterface), new(*authorRepo)) wire.Bind可以指定结构体实现的接口,如果结构体的New函数返回值不是显示声明为其实现的接口,那么wire会报错,此时就需要使用Bind方法进行绑定。 wire.Value // provider.go type Foo struct { X int }// wire.go ... wire.Build(wire.Value(Foo{X: 42})) ... 虽不常见,但有时需要为基本类型的属性绑定具体值, 这时可以使用 wire.Value wire.Build(wire.InterfaceValue(new(io.Reader), os.Stdin)) 为接口类型绑定具体值,可以使用 wire.InterfaceValue wire.FieldsOf 有时我们只是需要用某个对象的属性作为Provider,例如: ...