介绍在项目开发中,经常用到到保证数据安全的锁的使用。
sync.Mutex 互斥锁
- demo通过mu互斥锁保证写入数据和读取数据都是线程安全的。如果不用锁,在多个协程里执行SetNumber()容易导致获取的数据和预期不一致
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23type Item struct {
mu sync.Mutex
number int
}
// NewItem
func NewItem() *Item {
return &Item{
mu: sync.Mutex{},
number: 0,
}
}
// SetNumber
func (item *Item) SetNumber(num int) {
item.mu.Lock()
defer item.mu.Unlock()
item.number = num
}
// Number
func (item *Item) Number() int {
item.mu.Lock()
defer item.mu.Unlock()
return item.number
}
RWMutex 读写锁
在读多写少的场景中,可以优先使用读写锁RWMutex。
1 | package main |
sync.WaitGroup
WaitGroup相当于协程任务的管理者,监控受管理的协程是否已执行完成。
1 | func main() { |
分布式Redis锁
往往在服务端都是集群模式,在需要对数据进行安全的线性操作时,需要用到分布式锁。以下就是基于Redis实现的分布式锁。
1 | // RedisLock Redis锁 |
双向锁DoubleLock
在日常的项目中,时常会有类似转账的业务。当A向B转账的同时,B向A转账,如果仅仅简单的在账户的基础上加锁,A向B转账,加锁A,加锁B,此刻B向A转账,加锁B,再锁A,此刻会产生循环死锁。
解决方案:解开循环锁的关键,就在于固定加锁的顺序。比如:不管A向B转账,或者是B向A转账,都先加锁A,再加锁B。
1 | // DoubleLock |
- 本文作者: Hongker
- 本文链接: https://hongker.github.io/2020/03/31/golang-lock/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!