设计思路
- 使用Mutex进行基本保护:使用Go语言中的
sync.Mutex
来保护共享的用户会话信息,确保同一时间只有一个goroutine能够修改该信息。
- 读写分离优化:对于读操作远多于写操作的场景,可以考虑使用
sync.RWMutex
,允许多个goroutine同时进行读操作,只有写操作时才需要独占锁,从而减少锁争用。
- 减少锁的粒度:如果可能,将大的共享数据结构拆分成多个小的部分,每个部分使用单独的锁,这样不同的goroutine可以同时操作不同部分的数据,减少锁争用。
- 使用缓存:对于一些不经常变化的数据,可以使用缓存来存储,减少对共享数据的读取频率,从而减少锁争用。
关键部分代码实现
- 使用
sync.Mutex
的简单示例
package main
import (
"fmt"
"sync"
)
// UserSession 表示用户会话信息
type UserSession struct {
data map[string]interface{}
mu sync.Mutex
}
// Get 获取会话数据
func (us *UserSession) Get(key string) interface{} {
us.mu.Lock()
defer us.mu.Unlock()
return us.data[key]
}
// Set 设置会话数据
func (us *UserSession) Set(key string, value interface{}) {
us.mu.Lock()
defer us.mu.Unlock()
if us.data == nil {
us.data = make(map[string]interface{})
}
us.data[key] = value
}
func main() {
var wg sync.WaitGroup
session := UserSession{}
// 模拟多个goroutine操作会话数据
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
key := fmt.Sprintf("key%d", id)
session.Set(key, id)
value := session.Get(key)
fmt.Printf("Goroutine %d set and got: %v\n", id, value)
}(i)
}
wg.Wait()
}
- 使用
sync.RWMutex
优化读操作
package main
import (
"fmt"
"sync"
)
// UserSession 表示用户会话信息
type UserSession struct {
data map[string]interface{}
mu sync.RWMutex
}
// Get 获取会话数据
func (us *UserSession) Get(key string) interface{} {
us.mu.RLock()
defer us.mu.RUnlock()
return us.data[key]
}
// Set 设置会话数据
func (us *UserSession) Set(key string, value interface{}) {
us.mu.Lock()
defer us.mu.Unlock()
if us.data == nil {
us.data = make(map[string]interface{})
}
us.data[key] = value
}
func main() {
var wg sync.WaitGroup
session := UserSession{}
// 模拟多个读操作
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
key := fmt.Sprintf("key%d", id)
value := session.Get(key)
fmt.Printf("Goroutine %d read: %v\n", id, value)
}(i)
}
// 模拟一个写操作
wg.Add(1)
go func() {
defer wg.Done()
session.Set("newKey", "newValue")
fmt.Println("Write operation completed")
}()
wg.Wait()
}