我现在在模仿写一个数据库缓存的功能, 有一个单例类管理着 map<int, *p> 变量 提供接口访问和修改,我在写入的时候上锁,读的时候没有。 因为会有删除的情况,所以现在情况是这样的: 线程A读的时候获取了map的一份拷贝,对pA进行操作。 正常情况下, 是没问题的。 但如果这个时候有线程B,获取了map的引用,然后把pA删除掉了。 回到线程A的情况,线程A在if(pA)的时候,p所指向的对象还没有被删除,所以进入了if里面,但是切换到了线程B,线程B把p指向的对象删除掉了。这个时候回到线程,pA->DoSth();就会出错 请问一下大家是怎么处理这种情况的? 我设计的时候,其实一个map就对应数据库的一张表,int是表记录的主键,有多少条记录就有多少个*p; 之所以这样设计,是因为不同的表创建一个类,他们都继承同一个类,这样存的时候无论什么表的类,都能直接存到map里面,用的时候在强转回表的类就行了。 这种情况应该怎么避免pA->DoSth()出错呢?对map读上锁感觉太耗性能了 |
|
20分 |
读写锁
你测试过读写锁是性能瓶颈?还是臆想的? |
20分 |
读写的并发程度很高吗
|
40分 |
在保证正确性的前提下再考虑性能,你光顾着性能的话,那写的时候也可以不用加锁啦
读的时候不加锁,对于线程A来说是不负责任的,因为你没法控制系统的线程调度,除非此时线程B也是执行的读操作,那么你也许会想:可不可以对B的操作进行判断,如果是读操作A就不加锁,否则就加锁,哈哈,关键是A根本就不知道B会干什么,所以A要自保,所以读的时候也加上锁! 至于性能,你可以从别的方面下手,比如优化整体的流程,架构。 |
还没测试过,主要是数据会频繁操作,所以才把数据库的内容读到内存里面操作。 我读没上锁,因为网上搜了一些资料好像都说读的时候不上锁,写的时候才上锁。 因为我读的时候是获取map的一份拷贝,然后在操作的 =- = |
|
如果要上读写锁,是为每一个类都加吗?因为是这样的,map<int, *p> 有a1、a2、a3、a4等等,然后a1里面可能存了1000条记录。如果我读或者写a1里面的第一条数据时上锁,另外线程读写第1000条记录,却因为只给a1上锁而等待第一条处理完。总觉得有点浪费。。 还是我想太多有强迫症 = =··· |
|
且不说用智能指针能不能达到你要的效果,就算能达到,那修改操作呢?A在访问数据的同时,B把数据给修改了怎么办呢? 我倒是有个想法:可以参照MYSQL里的表级锁和行级锁来实现,按你的说法,map里的每对k/v对应的是主键/记录,那么可以试着在操作每条记录的时候上锁,而不是对整个map上锁,这样在操作第1000条记录的时候就不用等待第1条记录操作结束了。 你可以想先具体怎么实现行级锁,我试着想了一下实现方案,有点复杂,呵呵,mark一下,等有空了来搞搞! |
|
20分 |
还是加锁比较安全吧
|
哈哈,我本来也这样想,但觉得好像太复杂了就放弃了= =··· 有空搞一下 |
|
唉,也是,还是加锁安全一些 |