分享
 
 
 

Java Double-Checked Locking 已死,C++ 呢?

王朝c/c++·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

已经有众多文章讨论 double-checked locking 模式在 Java 下面无法正常工作,这里先简要的总结一下。

根本原因在于 Java 的 memory model 允许所谓的 out-of-order write ,对于下面的 Java 代码,out-of-order write 可能导致灾难性的结果

public static Singleton getInstance()

{

if (instance == null)

{

synchronized(Singleton.class) { //1

if (instance == null) //2

instance = new Singleton(); //3

}

}

return instance;

}

问题的起因在于语句 //3 ,JIT 所生成的汇编代码所作的事情并不是先生成一个 Singleton 对象,然后将其地址赋予 instance 。相反,它的做法是

1. 先申请一块空内存

2. 将其地址赋予 instance

3. 在 instance 所指的地址之上构建对象

下面的汇编代码提供了证明,说明这不只是一个脑筋急转弯,而是实际发生在 JIT 里面的。代码来自 Peter Haggar 的文章,我只是引用一下。

054D20B0 mov eax,[049388C8] ;load instance ref

054D20B5 test eax,eax ;test for null

054D20B7 jne 054D20D7

054D20B9 mov eax,14C0988h

054D20BE call 503EF8F0 ;allocate memory

054D20C3 mov [049388C8],eax ;store pointer in

;instance ref. instance

;non-null and ctor

;has not run

054D20C8 mov ecx,dword ptr [eax]

054D20CA mov dword ptr [ecx],1 ;inline ctor - inUse=true;

054D20D0 mov dword ptr [ecx+4],5 ;inline ctor - val=5;

054D20D7 mov ebx,dword ptr ds:[49388C8h]

054D20DD jmp 054D20B0

其中地址为 054D20BE 的代码正在分配内存,而接下来的一行将其赋予 instance ,这个时候 Singleton 的构造函数根本就还没有被调用。

那么问题在哪里?如果线程调度发生在 instance 已经被赋予一个内存地址,而 Singleton 的构造函数还没有被调用的微妙时刻,那么另一个进入此函数的线程会发觉 instance 已经不为 null ,从而放心大胆的将 instance 返回并使用之。但是这个可怜的线程并不知道此时 instance 还没有被初始化呢!

症结在于:首先,构造一个对象不是原子操作,而是可以被打断的;第二,更重要的,Java 允许在初始化之前就把对象的地址写回,这就是所谓 out-of-order 。

那么,对于 C++ 呢?典型的 C++ double-checked locking 可能是这样的

static Singleton* getInstDC()

{

if(inst_ == 0)

{

boost::mutex::scoped_lock l(guard_);

if(inst_ == 0)

inst_ = new Singleton();

}

return inst_;

}

正如 Java 的行为取决于 JIT 的处理方式,C++ 程序的行为要由编译器来决定。如果某个编译器的处理与 JIT 类似,那么 C++ 程序员也只好对 double-checked locking 说再见。下面是 VC7.1 在 release 配置下生成的代码:

static Singleton* getInstDC()

{

00401110 mov eax,dword ptr fs:[00000000h]

00401116 push 0FFFFFFFFh

00401118 push offset __ehhandler$?getInstDC@Singleton@@SAPAV1@XZ (4095F8h)

0040111D push eax

if(inst_ == 0)

0040111E mov eax,dword ptr [Singleton::inst_ (40D000h)]

00401123 mov dword ptr fs:[0],esp

0040112A sub esp,8

0040112D test eax,eax

0040112F jne Singleton::getInstDC+6Eh (40117Eh)

{

boost::mutex::scoped_lock l(guard_);

00401131 mov ecx,offset Singleton::guard_ (40D004h)

00401136 mov dword ptr [esp],offset Singleton::guard_ (40D004h)

0040113D call boost::mutex::do_lock (401340h)

00401142 mov byte ptr [esp+4],1

if(inst_ == 0)

00401147 mov eax,dword ptr [Singleton::inst_ (40D000h)]

0040114C test eax,eax

0040114E mov dword ptr [esp+10h],0

00401156 jne Singleton::getInstDC+57h (401167h)

inst_ = new Singleton();

00401158 push 1

0040115A call operator new (4011A2h)

0040115F add esp,4

00401162 mov dword ptr [Singleton::inst_ (40D000h)],eax

}

00401167 mov ecx,offset Singleton::guard_ (40D004h)

0040116C mov dword ptr [esp+10h],0FFFFFFFFh

00401174 call boost::mutex::do_unlock (401360h)

return inst_;

00401179 mov eax,dword ptr [Singleton::inst_ (40D000h)]

}

0040117E mov ecx,dword ptr [esp+8]

00401182 mov dword ptr fs:[0],ecx

00401189 add esp,14h

0040118C ret

从标记为红色的那一句,我们看到了希望:对 inst_ 的赋值发生在 new 完成之后,这意味着至少在 VC7.1 中,我们尚且可以放心使用 double-checked locking ,尽管它未必具有可移植性。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有