double-check
来源:互联网 发布:uujuly淘宝 编辑:程序博客网 时间:2024/05/17 05:15
ACE_Singleton 的 instance的实现:
template <class TYPE, class ACE_LOCK> TYPE *ACE_Singleton<TYPE, ACE_LOCK>::instance (void){ ACE_TRACE ("ACE_Singleton<TYPE, ACE_LOCK>::instance"); ACE_Singleton<TYPE, ACE_LOCK> *&singleton = ACE_Singleton<TYPE, ACE_LOCK>::instance_i (); // Perform the Double-Check pattern... if (singleton == 0) { if (ACE_Object_Manager::starting_up () || ACE_Object_Manager::shutting_down ()) { // The program is still starting up, and therefore assumed // to be single threaded. There's no need to double-check. // Or, the ACE_Object_Manager instance has been destroyed, // so the preallocated lock is not available. Either way, // don't register for destruction with the // ACE_Object_Manager: we'll have to leak this instance. ACE_NEW_RETURN (singleton, (ACE_Singleton<TYPE, ACE_LOCK>), 0); } else {#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) // Obtain a lock from the ACE_Object_Manager. The pointer // is static, so we only obtain one per ACE_Singleton // instantiation. static ACE_LOCK *lock = 0; if (ACE_Object_Manager::get_singleton_lock (lock) != 0) // Failed to acquire the lock! return 0; ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *lock, 0); if (singleton == 0) {#endif /* ACE_MT_SAFE */ ACE_NEW_RETURN (singleton, (ACE_Singleton<TYPE, ACE_LOCK>), 0); // Register for destruction with ACE_Object_Manager. ACE_Object_Manager::at_exit (singleton, 0, typeid (TYPE).name ());#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) }#endif /* ACE_MT_SAFE */ } } return &singleton->instance_;}
double-check技术主要是解决线程安全问题,避免在初始化时多线程重入,导致instance被实例化两次。
使用Double Checked Locking模式带来的几点好处:
1、最小化加锁。通过实现两个flag检测,Double Checked Locking模式实现通常用例的优化。一旦flag被设置,第一个检测将保证后续的访问不要加锁操作。
2、防止竞争条件。对flag的第二个检测将保证临界区中的事件仅实现一次。
使用Double Checked Locking模式也将带来一个缺点:产生微妙的移植bug的潜能。这个微妙的移植问题能够导致致命的bug,如果使用Double Checked Locking模式的软件被移植到没有原子性的指针和正数赋值语义的硬件平台上。例如,如果一个instance_指针被用来作为Singleton实现的flag,instance_指针中的所有位(bit)必须在一次操作中完成读和写。如果将new的结果写入内存不是一个原子操作,其他的线程可能会试图读取一个不健全的指针,这将导致非法的内存访问。
在一些允许内存地址跨越对齐边界的系统上这种现象是可能的,因此每次访问需要从内存中取两次。在这种情况下,系统可能使用分离的字对齐合成flag,来表示instance_指针。
如果一个过于激进(aggressive)编译器通过某种缓冲手段来优化flag,或是移除了第二个flag==0检测,将带来另外的相关问题。下面使用volatile关键字来解决这个问题:
private: static volatile long Flag_; // Flag is volatile.使用volatile将保证编译器不会将flag缓冲到编译器,同时也不会优化掉第二次读操作。使用volatile关键字的言下之意是所有对flag的访问是通过内存,而不是通过寄存器。
- double check
- double-check
- double-check
- Singleton和Double Check
- lock与double check
- Double-Check Locking
- java double check lock
- double check lock
- double check locking
- Java (Double-Check)
- 双重锁定 Double-Check Locking
- Double Check Locking Pattern DCLP
- java 的double-check locking
- Java 中的Double Check Lock
- Java 中的Double Check Lock
- Singleton与Double Check机制
- Double check 双重锁检查
- Double Check Locking -- Java并发
- 使用SOAP访问Web服务
- AndEngine开发的华容道
- Devexpress 自定义打印
- SQL小数点四舍五入(转)
- 纯代码写Navigation Bar
- double-check
- Tuxedo性能调优经验谈
- PM成长日记第三话-那些年我们一起做过的项目
- 读刘未鹏【如何有效的记忆与学习】
- ORA-01830: 日期格式图片在转换整个输入字符串之前结束
- Android eclipse中程序调试
- 显示隐藏div对象
- Java内部类的this问题
- linux 内核模块 参数