FAA
func transferFaa(balance *int32, amount int, done chan bool) {
atomic.AddInt32(balance, int32(amount))
done <- true
}
java.util.concurrent.
atomic.AtomicLong#getAndAdd
-
FAA原语
获取变量当前值,然后把它做个加法,且保证该操作的原子性,一行代码即可。你开始好奇了,那CAS还有何意义?
该案例肯定FAA更合适,但CAS适用范围更广。
类似逻辑:先读数据,做计算,然后更新数据,无论这个计算啥样,都可用CAS保护数据安全。
但FAA逻辑局限于简单加减法。所以并非说CAS没有意义。
使用CAS反复重试赋值比较耗费CPU,因为for循环如果赋值不成,会立即进入下一次循环,没有等待的。如果线程间碰撞频繁,经常反复重试,这重试的线程会占用大量CPU时间,系统性能就会下降。
缓解这问题的一个方法是使用Yield(), 大部分编程语言都支持Yield()系统调用。
Yield()作用
告诉os,让出当前线程占用的CPU给其他线程。每次循环结束前调用下Yield(),可在一定程度上降低CPU使用率,缓解该问题。也可在每次循环结束后,Sleep()小段时间,但这样性能会严重下降。
所以,这种方法它只适于线程碰撞不太频繁,即执行CAS不需要重试这样的场景。
用锁、CAS和FAA完整实现账户服务
ttps://github.com/shenyachen/JKSJ/blob/master/study/src/main/java/com/jksj/study/casAndFaa/CASThread.java
https://github.com/xqq1994/algorithm/blob/master/src/main/java/com/test/concurrency/MutxLock.java https://github.com/xqq1994/algorithm/blob/master/src/main/java/com/test/concurrency/CAS.java参考
https://time.geekbang.org/column/article/130743![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5yY4IWOwImNhNDN5IjM0MmYzQzY0UzY3EmYhJmY0MGM48CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.png)