ace allocator 和 singleton 的线程安全

来源:互联网 发布:mac os 应用程序 推荐 编辑:程序博客网 时间:2024/04/29 13:00

最近因为需要,继承实现了一个 ace_cached_allocator的分配器,理由是原本的ace_cached_allocator的实现不提供自增长的功能,当申请超过预分配的大小个数时,内存池将返回NULL。而提供动态增长的ace_local_memory_pool由于支持动态长度而显得不那么高效,项目需要的是定长的快,为专有块提供专有的memory_pool。实现起来也很简单,继承ace_new_allocator, 实现malloc ,calloc, free 三个接口,内部用简单的链表把块和freeblock相连就完事了。但测试起来就没那么顺利了,多线程下跑一会就有问题。查看了一下发现问题在于对ace线程安全策略理解有误有关。

内存池用的是单件模式, ace_singleton<ace_cached_allocator_ex<data,ace_lock1 >,ace_lock2>   一开始我认为 ace_lock1 和 ace_lock2 择1则可,因为单件使用时lock了,内存池就安全了。结果ace_lock1 就用的 是 ace_synch_null_mutex ,ace_lock2 用 ace_synch_mutex 。结果自然是悲剧,后来查看了一下这2个模板的实现发现 ace_lock2 虽然保住了ace_singleton的线程安全,但仅仅保证的是在取得这个单件的时候,至于单件以后的使用是非安全的。而ace_lock2才是真正保证内存池中malloc和free时候的链表安全的。如果觉得ace_lock1有了ace_lock2就不必了也有问题,因为ace_singleton本身在第一次取得的时候会用给static 变量赋值的方式完成初始化,没有ace_lock1以后难保会产生2份。

顺带提一下这种用模板的方式实现的锁本身会由于ace_synch_null_mutex  这种对象的空方法 达到编译后 非线程安全 方法的 调用效率。

原创粉丝点击