创作人 Leo


编辑时间 Wed Aug 26,2020 at 17:49


悲观锁

悲观锁假设对象总是会被修改, Golang 中 sync 包中 Mutex,RWMutex 都属于悲观锁

乐观锁

CAS - Compare And Set
乐观锁假设对象没有被修改,如果发现被修改则重新尝试

这是一段没有使用原子操作的有问题的代码,它不会产生预期的结果
它的结果大概输出 6000-7000 之间数字

func atomDemoBug() {
	var wg sync.WaitGroup

	for i:=0; i<10; i++ {
		wg.Add(1)
		go func(){
			for j:=0; j<1000; j++ {
				counter = counter+1
			}
			wg.Done()
		}()
	}

	wg.Wait()

	fmt.Println(counter)
}

Golang sync.atomic 包含了一系列原子操作,都是基于乐观锁实现

func atomDemo() {
	var wg sync.WaitGroup

	for i:=0; i<10; i++ {
		wg.Add(1)
		go func(){
			for j:=0; j<1000; j++ {
				// sync.atomic 包含了一系列原子操作
				atomic.AddInt32(&counter, 1)
			}
			wg.Done()
		}()
	}

	wg.Wait()

	fmt.Println(counter)
}

atomic 的 doc.go 有一段话

// These functions require great care to be used correctly.
// Except for special, low-level applications, synchronization is better
// done with channels or the facilities of the sync package.
// Share memory by communicating;
// don't communicate by sharing memory.

ABA 问题

乐观锁的 ABA 问题是多个线程修改一个对象,竞争条件下会造成来回修改问题
假设提款机 ATM 遵循 CAS ,用户 L 余额 100 提款 50 ,这是提款机有问题,开启了两个提款线程,正常情况下线程 A 将余额改为 50,则线程 B 执行失败,而这个有BUG的提款机线程 B 由于网络问题卡住了,同时用户 L 收到了一笔50的存款,然后线程 B 恢复运行,compare 发现 余额 100 正常,执行了扣款 50 ,于是用户 A 凭空消失 50 块 。


阅读:72
搜索
  • Linux 高性能网络编程库 Libevent 简介和示例 1927
  • Mac系统编译PHP7【20190929更新】 1796
  • Windows 安装Swoole 1558
  • Hadoop 高可用集群搭建 (Hadoop HA) 1472
  • Hadoop 高可用YARN 配置 1402
  • 小白鼠问题 1324
  • Hadoop Map Reduce 案例:好友推荐 1267
  • 自动化测试工具 Selenium 1131
  • GIT 分支管理 1064
  • Golang 使用 Grpc 985
简介
不定期分享软件开发经验,生活经验