互斥锁与自旋锁
在现实生活中,锁的作用无非是将物品关起来,防止被他人进入等。而在程序中锁的概念也是如此,当同一个内存地址被同时访问时,会造成数据竞争,意思是不知道当前变量被谁所操作,所以引入了锁的概念,当有人来访问时,对此变量加上一把锁来防止其他对象对其访问,这样才会更安全的使用变量做操作。现实中锁的种类有多种,比如物理锁、指纹锁等。在程序中亦是如此,这里大类氛围两种,互斥锁和自旋锁。 1. 数据竞争(Data Race)1 Data Race 又称 Race Condition。它旨在描述一个系统或者进程的输出依赖于不受控制的事件出现顺序或者出现时机。此词源自于两个信号试着彼此竞争,来影响谁先输出。 计算机为了提高性能,出现了多线程和多进程,增加了执行并行能力,但是在保持数据一致上就需要外力来维持。而造成这一原因的就是数据竞争,多个执行者对一个事物的操作。最为常见的例子是在银行存取款,如果付款存在多个交易时较为容易出现这类问题。 事例 如果你银行卡中有余额 1000 元,当你同时购买两个售价分别是 100 和 200 元的商品时,在银行账户中的操作可能是这样的 1000 -100 = 900 // 购买 100 元商品时扣款 900 - 200 = 700 // 购买成功第一个商品后,扣款 200 元商品 1000 - 200 = 800 // 购买 200 元善品时扣款 余额可能是这三种,因为在同时付款的时候,你不知道哪个扣款是先处理操作。所以会出现上述情况,按理说付款完成后余额剩余 700 才是正确的,但是为什么会出现这种情况,是因为出现了数据竞争,但进行扣款操作时候,两者都拿到了总额为 1000 的进行扣除,其中有一方肯定错误的扣除处理。 # 使用Golang实现 package main import ( "fmt" "sync" ) // 余额 var Balance uint = 1000 // wg var wg sync.WaitGroup // 消费行为 func consume(money uint) uint { defer wg.Done() Balance -= money return Balance } func do() { defer wg.Wait() goods := [2]uint{100, 200} // 同时有两款交易进行中 for i := range goods { wg.Add(1) go func(i int) { fmt.Printf("Current balance is: %v\n", consume(goods[i])) }(i) } } 运行函数do(),得到输出为: ...