在高并发系统开发时,由于涉及到多线程,不可避免的会对一些需要独占处理的资源进行加锁处理。但是加锁的话势必会导致锁竞争,若是锁竞争激烈的话会极大影响并发处理效率。因此在写代码的时候需要注意降低锁竞争,以下是一些思路整理:
1、缩小锁的范围,无需独占处理的代码一定移到同步代码块之外
2、减少锁竞争,例如ConcurrentHashMap的锁分段技术,将需同步的范围拆分成几份,分别用锁控制
3、CopyOnWrite思想,将需要加锁处理的资源先复制一份,处理完再替换对象引用,如CopyOnWriteArrayList
4、使用ThreadLocal,threadlocal内对象只有本线程可以查看或添加,就不存在竞争问题,但需注意业务处理完需remove,否则有内存泄漏风险
5、使用读写锁,对于读多写少的场景可以使用reentrantReadWriteLock,可多线程并发读,单线程写,但是这个锁在读请求远远大于写请求时容易导致写线程饥饿,无法争抢到锁,可以采用jdk1.8提供的乐观锁stampedLock
6、使用乐观锁,例如简单的计数可以用Atomic系列原子类,通过自旋+CAS提高效率。
7、无锁化编程,例如netty的设计,每个链接实例化一条pipeline,里面的handler都是new出来的,多线程之间各自有自己的pipeline,无需加锁
8、利用CAS+volatile降低锁粒度,例如普通生产者消费者模式用linkedBlockingQueue,每次往队列里put数据都需争抢锁,而著名的Disruptor框架采用CAS往队列中放入数据,只有数据达到最大容量了才加锁阻塞,极大提高吞吐量
9、如果单线程能满足性能要求就没必要用多线程,例如Redis就是单线程模型,可以消除锁竞争