diff --git a/eBook/19.3.md b/eBook/19.3.md index 619352f..c4efea0 100644 --- a/eBook/19.3.md +++ b/eBook/19.3.md @@ -37,7 +37,7 @@ url := m["a"] ## 使程序线程安全 -这里,变量 `URLStore` 是中心化的内存存储。当收到网络流量时,会有很多 `Redirect` 服务的请求。这些请求其实只涉及读操作:以给定的短 URL 作为键,返回对应的长 URL 的值。然而,对 `Add` 服务的请求则大不相同,它们会更改 `URLStore`,添加新的键值对。当在瞬间收到大量更新请求时,可能会产生如下问题:添加操作可能被另一个相同请求打断,写入的长 URL 值可能会丢失;另外,读取和更改同时进行,导致可能读到脏数据。代码中的 map 并不保证当开始更新数据时,会彻底阻止另一个更新操作的启动。也就是说,map 不是线程安全的,goto 会并发地为很多请求提供服务。因此必须使 `URLStore` 是线程安全的,以便可以从不同的线程访问它。最简单和经典的方法是为其增加一个锁,它是 Go 标准库 `sync` 包中的 `Mutex` 类型,必须导入到我们的代码中(关于锁详见 [9.3 节](09.3.md))。 +这里,变量 `URLStore` 是中心化的内存存储。当收到网络流量时,会有很多 `Redirect` 服务的请求。这些请求其实只涉及读操作:以给定的短 URL 作为键,返回对应的长 URL 的值。然而,对 `Add` 服务的请求则大不相同,它们会更改 `URLStore`,添加新的键值对。当在瞬间收到大量更新请求时,可能会产生如下问题:添加操作可能被另一个同类请求打断,写入的长 URL 值可能会丢失;另外,读取和更改同时进行,导致可能读到脏数据。代码中的 map 并不保证当开始更新数据时,会彻底阻止另一个更新操作的启动。也就是说,map 不是线程安全的,goto 会并发地为很多请求提供服务。因此必须使 `URLStore` 是线程安全的,以便可以从不同的线程访问它。最简单和经典的方法是为其增加一个锁,它是 Go 标准库 `sync` 包中的 `Mutex` 类型,必须导入到我们的代码中(关于锁详见 [9.3 节](09.3.md))。 现在,我们把 `URLStore` 类型的定义更改为一个结构体(就是字段的集合,类似 C 或 Java ,[10 章](10.0.md) 介绍了结构体),它含有两个字段:`map` 和 `sync` 包的 `RWMutex`: ```go