双重检测优化与加锁操作redis
今天,学习了公司大佬的代码,又又又发现了一些让我迷惑的写法... ...
在我对redis浅显的认知中,redis是单线程多路io复用的,那么既然是单线程的话,我想应该大概也许可能不涉及到线程安全的问题吧。
但是,今天在大佬的代码中,发现了一个读写redis的方法加了锁,方法做的事情很简单,开始我并不理解操作redis为什么要加锁,直到在网上找了一些资料之后,才明白可能存在读到脏数据的问题。
比如有两个线程都要从redis中读取一个值,将其加10,再回写回redis,数据初始值为0。
我们期望得到的结果是20,但最后可能结果为10。
假设,第一个线程读取数据0,将其加10,但并未来得及写入redis,然后时间片就结束了。此时,轮到第二个线程读取数据,那么获取到的数据依然为0,将其加10,依然没有写入redis时间片就结束了。
现在,线程一将redis中的值改为10,线程二依然会将redis中的值改为10,最终结果为10。
大佬的代码中使用了缓存来降低数据库的压力,按照我之前的理解,在一个读取数据的方法中,首先读取缓存信息,如果获取不到数据,则读取数据库信息并写入缓存。
但大佬的思路是,首先读取缓存信息,如果获取不到数据,则再次读取缓存信息,如果还是获取不到数据,则读取数据库信息并写入缓存。
刚开始很迷惑,这样做的意义何在?忽然之间,想到了单例模式的一种实现,双重检测,其中的一层检测是为了提高效率。由于项目中采用了多线程,所以在第一个线程没有从缓存中获取到数据之后,有可能其他线程已经完成了读取数据库写入缓存的操作,也就是说,第一个线程再次得到时间片的时候,就没有必要访问数据库获取数据了。