并发时,解决数据竞争的方案
文档更新说明
- 最后更新 2019年01月25日
- 首次更新 2019年01月25日
前言
简述并发时, 对公共数据的访问出现的数据竞争问题和解决思路.
数据竞争
当同一时间有多个线程(或者goroutine)去读取同一块数据(变量), 因为没有涉及到写入操作, 所以是并发安全的. 但是如果其中有一个线程有写入操作(正常都是有写入操作的), 那么就一定会出现数据竞争问题, 即两个线程同时读取数据之后, 又同时写入数据, 这个时候肯定有一个线程写入的数据会丢失.举个例子
1 | i := 0 |
那么结果i最终可能是15, 也可能是5或者10
解决数据竞争的方法
- 不要写变量, 设计成只读操作. 也就是一开始把数据都生成好了, 以后只读就可以啦. (这个太天真了, 数据一般都是有更新操作的)
- 让变量只被一个线程访问. 也就是说存在一个线程专门(monitor)用来更新变量, 其他线程需要更新变量的时候, 则向这个线程发个消息,由monitor负责更新即可.
- 串行绑定. 这个比较难理解, 就是一个变量可以在多个线程里存在, 但是却是按照顺序, 先进入线程1, 再进入线程2
- 互斥访问. 这个比较常见了, 一个线程访问公共变量的时候加一个锁, 访问结束再释放锁. 这样就确保了同一时间内只有一个线程能访问到.
例子
上述几种方法, 都可以在<Go语言圣经>第9章第1节中找到详细例子