对于锁的性能提升的考虑,主要包括以下几点
- 减小锁持有时间
- 减小锁粒度
- 读写分离锁来替换独占锁
- 锁分离
- 锁粗化
1. 减小锁持有时间
简而言之,只在必要时进行同步。
对于一个需要加锁的代码块而言,其中如果有独立的、可以移出同步块的代码,那么就应该将其移出,使得同步块的内容尽可能少,执行时间尽可能短。另一方面,减少锁的持有时间,有助于降低锁冲突的可能性,进而提升系统的并发能力。
2. 减小锁粒度
以ConcurrentHashMap为例,其内部细分了若干个小的HashMap,称为段,默认情况下,一个ConcurrentHashMap将被细分为16个段。借助于段的机制,ConcurrentHashMap只需要对段的粒度加锁,就可以保证线程安全,而不必对整个ConcurrentHashMap进行枷锁。
需要注意的是,减小锁粒度需要考虑全部锁的场景,比如对于ConcurrentHashMap,如果需要获取其size,这就不是段这个机制能够解决的了。
所谓的减少锁粒度,就是指缩小锁定对象的范围,从而减少锁冲突的可能性,进而提高系统的并发能力。
3. 读写分离锁来替换独占锁
Java所提供的读写锁:ReadWriteLock
读多写少的场景,使用读写锁可以有效提升系统的并发能力。相对于上述减小锁粒度的方案(通过分割数据结构)而言,读写锁则是对系统功能点的分割。
4. 锁分离
锁分离是读写锁的进一步延伸。
举个例子,在LinkedBlockingQueue中,put()与take()方法都对当前队列进行了修改操作,但是它们总是分别作用于尾端与前端,从理论上说,两着并不冲突。因此,在JDK的实现中,使用了两把锁来取代独占锁的设计,分离了put()与take()操作。
5. 锁粗化
锁粗化意图在于减少锁的申请与释放次数,其思想与减少锁的持有时间是相反的。但是在不同场合,需要根据实际情况,进行权衡。
网友评论