1考虑读多写少(乐观锁)还是 写多读少(悲观锁) 悲观锁与乐观锁的区别在于是否锁定资源
例如令牌桶限流算法中,写多读少的场景
在guava RateLimter 实现中,使用 volatile 和 synchronized 进行实现,只是单机jvm级别,如果是分布式,则可以使用redis实现相关的分布式锁,setnx和lua脚本实现
java中悲观锁和乐观锁有哪些?
悲观 synchronized ReentrantLock
乐观锁 juc下面的工具类比如AtomicInteger
减少锁的竞争
1)通过使用synchronized代码块儿代替在方法上添加synchronized来保护共享状态的方法,减小锁的范围,减少线程持有锁的时间。
2)锁的分解,例如一个类有两个共享状态,一个是人,一个是钱,分别提供两个锁,分别对应这两个共享状态,那么即可减少持有锁的频率。
3)锁的分解的进一步扩展那就是锁的分段,例如共享状态人是使用HashTable保存那么程序性能因为经常持有锁二成为性能瓶颈,使用ConcurrenthHashMap来代替Hashtable,因为ConcurrentHashMap使用的是默认16个锁类分别管理整个map的1/16的元素,那么每个线程在写入程序的时候,不需要持有整个map的锁,减少了持有锁的频率。
4)避免热点域,例如ConcurrentHashMap的size,用户保存集合的元素个数,单数看似可以O(1)操作的直接获取的操作,却因为是没有个设计修改元素个数的操作都会访问这个属性成为并发的另一个伸缩性问题,ConcurrrentHashMap通过每一个Segment维护一个count,这样在需要的时候再汇总,避免频繁访问size的问题。
5)合理使用volatile。