互斥锁 对于任一共享资源,同一时间保证只有一个操作者,这种方法称为 互斥机制。 关键字 Mutex 表示互斥锁类型,它的 Lock 方法用于获取锁,Unlock 方法用于释放锁。在 Lock 和 Unlock 之间的代码,可以读取和修改共享资源,这部分区域称为 临界区。 错误的并发操作 先来看一个错 …
对于任一共享资源,同一时间保证只有一个操作者,这种方法称为互斥机制
。
关键字Mutex
表示互斥锁类型,它的Lock
方法用于获取锁,Unlock
方法用于释放锁。在Lock
和Unlock
之间的代码,可以读取和修改共享资源,这部分区域称为临界区
。
先来看一个错误的示例。
在Map小节中讲到,Map
不是并发安全的,也就是说,如果在多个线程中,同时对一个 Map 进行读写,会报错。现在来验证一下, 通过启动100 个 goroutine
来模拟并发调用,每个 goroutine 都对 Map 的 key 进行设置。
packagemain
import"sync"
funcmain(){
m:=make(map[int]bool)
varwgsync.WaitGroup
forj:=0;j
通过输出信息fatal error: concurrent map writes
可以看到,并发写入 Map 确实会报错。
Map 并发写入如何正确地实现呢?
一种简单的方案是在并发临界区域 (也就是设置 Map key 的地方) 进行加互斥锁操作,互斥锁保证了同一时刻 只有一个 goroutine 获得锁,其他 goroutine 全部处于等待状态,这样就把并发写入变成了串行写入, 从而消除了报错问题。
packagemain
import(
"fmt"
"sync"
)
funcmain(){
varmusync.Mutex
m:=make(map[int]bool)
varwgsync.WaitGroup
forj:=0;j
利用channel (通道)
和time.After()
方法实现超时控制。
packagemain
import(
"fmt"
"time"
)
funcmain(){
ch:=make(chanbool)
gofunc(){
deferfunc(){
ch
调用time.NewTicker
方法即可。
packagemain
import(
"fmt"
"time"
)
funcmain(){
ticker:=time.NewTicker(time.Second)
deferticker.Stop()
done:=make(chanbool)
gofunc(){
time.Sleep(5*time.Second)//模拟耗时操作
done
-
1.互斥锁 – 维基百科 (https://zh.wikipedia.org/wiki/互斥锁)
-
2.临界区 – 百度百科 (https://baike.baidu.com/item/临界区/8942134)
联系我
声明:本站所有文章,如无特殊说明或标注,均为爬虫抓取以及网友投稿,版权归原作者所有。
暂无评论内容