注意:这个问题与其他并发问题不同,因为不仅写入器是单个的,而且写入操作严格地发生一次。
当一个Go语言有多个并发读取器和一个写一次且只写一次的写入器时,例如并发环境中的setter,使用什么方法进行同步?sync.Mutex
适用于这种情况,但是,由于只有一个writer,因此sync.RWMutex
甚至更好,因为它比常规互斥体稍微快一些。
但是,在应用程序运行期间执行互斥锁,只设置一次值,感觉很浪费。
有更快的路吗?
package main
import (
"sync"
)
type RWMutexErrorNotifier struct {
rwMutex sync.RWMutex
emailSender func(string)
}
func (a *RWMutexErrorNotifier) SetEmailSenderService(emailSender func(string)) {
a.rwMutex.Lock()
defer a.rwMutex.Unlock()
a.emailSender = emailSender
}
func (a *RWMutexErrorNotifier) SendErrorMessage(errorMessage string) {
a.rwMutex.RLock()
defer a.rwMutex.RUnlock()
if a.emailSender == nil {
return
}
a.emailSender(errorMessage)
}
func main() {
sender := &RWMutexErrorNotifier{}
errorsCount := 100_000
emailSender := func(emailMessage string) {
// sending email...
}
var wg sync.WaitGroup // used only for demo purposes
wg.Add(errorsCount)
for i := 0; i < errorsCount; i++ {
go func() {
sender.SendErrorMessage("ALARM!")
wg.Done()
}()
}
sender.SetEmailSenderService(emailSender) // making a single write
wg.Wait()
}
1条答案
按热度按时间x8diyxa71#
更新感谢@peter-cordes -请参见答案下方的评论
显然,对于单个writer的单次写入,阅读和设置
atomic.Bool
比sync.RWMutex
快。基准测试结果(基于
sync.Mutex
的解决方案也仅用于基准测试目的):基准: