并发安全,就是多个并发体在同一段时间内访问同一个共享数据,共享数据能被正确处理。

很多语言的并发编程很容易在同时修改某个变量的时候,因为操作不是原子的,而出现错误计算,比如一个加法运算使用中的变量被修改,而导致计算结果出错,典型的像统计商品库存。

channelchannel

我们可以不用,但不可以不了解,手中有粮心中不慌。

并发不安全的例子

appendcaplencap

所以在这个过程中,仅讨论扩容操作的话可能存在同时申请并赋值的情况,导致漏掉某次扩容增加的数据。

1000010000
  • 以上并发操作的同一个资源,专业名词叫做临界区
  • 因为并发操作存在数据竞争,导致数据值意外改写,最后的结果与期待的不符,这种问题统称为竞态问题

常见于控制商品减库存,控制余额增减等情况。 那么有什么办法解决竞态问题呢?

goroutine

这两个思路贯穿了无数的高并发/分布式方案,区别是在一个进程应用中使用,还是借助某些第三方手段来实现,比如中间件。独孤九剑森罗万象一定要牢牢记住。

互斥锁

Go

在访问临界区的前后加上互斥锁,就可以保证不会出现并发问题。

4.7.1
sgoroutine10000

读写锁

互斥锁是完全互斥的,并发读没有修改的情况下是不会有问题的,也没有必要在并发读的时候加锁不然效率会变低。

用法:

并发读不互斥可以同时,在一个写锁获取时,其他所有锁都等待, 口诀:读读不互斥、读写互斥、写写互斥。具体测算速度的代码可以见4.7.3的源码,感兴趣的可以改下注释位置看下效率是有很明显的提升的。

小结

sync.Mutexsync.RWMutexsync

问题:只加写锁可以吗?为什么?

总结