多线程中,我们经常会看到给出的一个建议,缩小加锁的范围。这个建议很好理解,大家都会谨记心中,写代码时也想着落地执行。
但是具体如何落地,这个就比较抽象了,很多时候,我们自己会觉得我这样做法就是最小的锁粒度,不可能再优化了。和考试的时候一样,老师经常让我们做完试卷,检查一下,大部分人也觉得没啥好检查的。
下面就一个常见的应用场景来说说,我们很多时候,要对一个List进行遍历,然后对list里的对象执行某个操作。这个时候,大家都很熟练,多线程嘛,防止其他线程对该list进行增加删除等操作,这里要加锁啊,我先加锁,然后遍历list,操作完成后,再解锁,完美。
这是再简单不过的三板斧了,你还能咋缩小加锁的范围,你说复杂的业务逻辑,你通过什么再设计,调整架构,可以缩小加锁的范围,我就一个简单的遍历list,怎么着也不会被打脸啊。
我最开始也是这么认为的,这就属于典型的没吃过猪肉,还没见过猪跑了。大佬给出的建议是,既然你担心其他线程对该list操作,那我们可以copy出一个临时list,那我们只需在copy的时候加所了,遍历该list时,对其中的对象执行操作,就不用加锁了,这样就缩小了锁的粒度。
本来写道这儿,就要结束了,今天看《多人在线游戏架构实战》这本书更狠,用gprof分析出这里对list的copy性能问题,提出了一个优化的方案,采用读写两个list,读操作时,如果此时要写入,返回另外一个list指针给外界,内部读写缓冲区可以根据条件交换,采用空间换时间的做法,优化了copy的时间。
从这里可以看出,还是要多看些书,否则自己都不清楚有哪些方法论,只会简单地下结论,我这个代码不可能再优化了,井底之蛙,先入为主,想提高就难了。