CAS以及在Java并发机制中的使用

Java 并发编程中有介绍CAS实现锁的机制,后面再看了一些编译原理方法的书,对锁的实现有一些基本了解。

提高并发减少上下文切换的方法:

  • 无锁并发编程:按Hash算法取模分段,不同的线程处理不同段数据。
  • CAS算法:CAS算法更新数据,无需加锁。
  • 使用最少线程:尽量用少的线程,不要造成等待。
  • 协程:在单线程里实现多任务的调度。

Java并发机制的底层实现

  • Volatile:将当前处理器缓存行数据回写到系统内存,并让其他缓存失效。
  • synchronized:同步代码块,锁定对象头。monitorenter和monitorexit指令。
  • 原子操作:通过锁和循环CAS的方式来实现原子操作。

JVM内部实现了很多种锁机制,有偏向锁、轻量级锁和互斥锁。有意思的是除了偏向锁,JVM实现锁的方式都用了循环CAS,即当一个线程想进入同步块的时候使用循环CAS的方式来获取锁,当它退出同步块的时候使用循环CAS释放锁。

单应用部署可以通过Java锁现实线程同步,当部署微服务时,需要锁定库存量时就需要想其他办法,Redis CAS操作实现乐观锁。

Redis乐观锁工作机制:

watch指令在Redis事物中提供了CAS的行为。watch 命令会监视给定的每一个key,当exec时如果监视的任一个key自从调用watch后发生过变化,则整个事务会回滚,不执行任何动作。注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然exec,discard,unwatch命令,及客户端连接关闭都会清除连接中的所有监视。还有,如果watch一个不稳定(有生命周期)的key并且此key自然过期,exec仍然会执行事务队列的指令。

实战应用:

当设计一个秒杀系统时候,为防止商品数量被超额购买,可以预先把库存数量加载到redis中,活动开始后服务端每次都通过Redis控制库存数量,同时使用watch命令实现CAS锁,如何Redis返回正常则走正常流程,如果否,则重试进入秒杀流程。通过Redis可以有效防止商品库存爆掉。

随想

我们在饿了么上面购买商品时候,涉及到支付,当我们购买一个商品后,因为某个原因没有支付,这时候订单会变成等待支付,这时候商品数量是应该减还是不减了。这个问题应该是一个产品问题,但是对应到代码层面我们会认为这就是悲观锁和乐观锁的设计区别。假定对系统数据流程要求很严格,可以直接使用悲观锁方式,直接先锁定数据,即库存数量减少,如果失败则回退库存,这样设计就会让很多用户因库存不够被排斥在外无法购买。乐观锁则只在支付完成后减库存,中间可以不断重试。支付的过程也是一个事务的过程,一般涉及2个步骤,预提交支付和最终确认支付,可能还涉及到支付余额不足的问题,都是在支付环节需要解决的问题。

 

 

 

 

 

 

 

 

 

 

参考:

https://www.jianshu.com/p/ae25eb3cfb5d

https://www.cnblogs.com/martinzhang/p/3415204.html

https://www.cnblogs.com/huobi/p/9844755.html

Java内存模型的基础以及内存语义

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章