并发访问问题
首先我们举例说下,并发访问问题有哪些?其实实际工作中我们会碰到很多,比如:
多个 goroutine 并发更新同一个资源,像计数器;同时更新用户的账户信息;秒杀系统;往同一个 buffer 中并发写入数据等等。如果没有互斥控制,就会出现一些异常情况,比如计数器的计数不准确、用户的账户可能出现透支、秒杀系统出现超卖、buffer 中的数据混乱,等等,后果都很严重。
那么如何解决这些问题呢? 可以用互斥锁, 在Go标准库就是 Sync.Mutex
**
互斥锁的实现机制
互斥锁是并发控制的一个基本手段。
在并发编程中,如果程序中的一部分会被并发的访问或修改,那被保护起来的程序,叫做临界区。
通俗的说,临界区就是一个被共享的资源。
如果很多线程同步访问临界区,那么就会造成访问或操作错误,使用互斥锁,会限定临界区只能同时由一个线程持有。
互斥锁很好的解决了资源竞争问题,互斥锁也叫排它锁。
同步原语的适用场景
- 共享资源。并发地读写共享资源,会出现数据竞争(data race)的问题,所以需要 Mutex、RWMutex 这样的并发原语来保护。
- 任务编排。需要 goroutine 按照一定的规律执行,而 goroutine 之间有相互等待或者依赖的顺序关系,我们常常使用 WaitGroup 或者 Channel 来实现。
- 消息传递。信息交流以及不同的 goroutine 之间的线程安全的数据交流,常常使用 Channel 来实现。