Go 中高效的共享映射实现技术
对共享数据结构的并发访问需要仔细考虑以确保数据完整性。考虑一个映射被多个 goroutine 同时访问的情况,如下例所示。
<code class="go">func getKey(r *http.Request) string { ... } values := make(map[string]int) http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) { key := getKey(r) fmt.Fprint(w, values[key]) }) http.HandleFunc("/set", func(w http.ResponseWriter, r *http.Request) { key := getKey(r) values[key] = rand.Int() })</code>
通过并发写入直接操作映射可能会导致数据不一致。如下所示,使用互斥体可以解决原子性问题,但会带来另一个问题。
<code class="go">func getKey(r *http.Request) string { ... } values := make(map[string]int) var lock sync.RWMutex http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) { key := getKey(r) lock.RLock() fmt.Fprint(w, values[key]) lock.RUnlock() }) http.HandleFunc("/set", func(w http.ResponseWriter, r *http.Request) { key := getKey(r) lock.Lock() values[key] = rand.Int() lock.Unlock() })</code>
虽然互斥体提供可靠的同步,但它们引入了手动锁定和解锁的复杂性。 Go 中更惯用的方法是利用通道。默认情况下,建议优先考虑通道而不是互斥体,正如 Go 的座右铭所例示的:“通过通信共享内存,不要通过共享内存进行通信。”
以下是一些关键注意事项:
以上是如何应用Go的并发原理来创建安全高效的共享地图?的详细内容。更多信息请关注PHP中文网其他相关文章!