在 Go 中,对共享映射的并发访问需要仔细考虑以避免非原子写入。虽然可以使用互斥体,但它们引入了可能与惯用的 Go 方法不一致的原语的使用。
一种替代方法是利用通道进行并发控制。这种方法符合“通过通信来共享内存,而不是通过共享内存来通信”的 Go 哲学。 goroutine 可以通过通道进行通信,而不是直接操作映射,从而确保对共享数据的独占访问。
例如,在原始代码中,可以进行以下修改:
<code class="go">// key retrieval logic remains the same values := make(map[string]int) var valueCh = make(chan string) var setCh = make(chan map[string]int) // Handler for GET requests http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) { key := getKey(r) valueCh <- key fmt.Fprint(w, <-valueCh) }) // Handler for SET requests http.HandleFunc("/set", func(w http.ResponseWriter, r *http.Request) { key := getKey(r) tmp := make(map[string]int) tmp[key] = rand.Int() setCh <- tmp }) // Map update goroutine go func() { for { select { case key := <-valueCh: valueCh <- values[key] case updatedMap := <-setCh: for k, v := range updatedMap { values[k] = v } } } }()</code>
在这个修改后的代码中:
通过采用这种基于通道的方法,代码变得更加惯用,简化了并发管理,并遵循 Go 原则避免共享内存。
以上是通道如何通过共享地图增强 Go 中的并发性?的详细内容。更多信息请关注PHP中文网其他相关文章!