// code snippet 1
static boost::thread_specific_ptr<StreamX> StreamThreadSpecificPtr;
void thread_proc() {
StreamX * stream = NULL;
stream = StreamThreadSpecificPtr.get();
if (NULL == stream) {
stream = new StreamX();
StreamThreadSpecificPtr.reset(stream);
}
printf("%p\n", stream);
}
int run() {
boost::thread_group threads;
for(int i = 0; i < 5; i ++) {
threads.create_thread(&thread_proc);
}
threads.join_all();
}
// the result is
0x50d560 -- SAME POINTER
0x50d540
0x50bfc0
0x50bef0
0x50d560 -- SAME POINTER
// code snippet 2
static boost::thread_specific_ptr<StreamX> StreamThreadSpecificPtr(NULL); // DIFF from code snippet 1
void thread_proc() {
StreamX * stream = NULL;
stream = StreamThreadSpecificPtr.get();
if (NULL == stream) {
stream = new StreamX();
StreamThreadSpecificPtr.reset(stream);
}
printf("%p\n", stream);
}
int run() {
boost::thread_group threads;
for(int i = 0; i < 5; i ++) {
threads.create_thread(&thread_proc);
}
threads.join_all();
}
// the result is
0x50d510
0x50d4f0
0x50bf70
0x50ca70
0x50be50
在代码片段1中,两个指针是相同的。不是预期的。 在代码片段2中,将StreamThreadSpecificPtr初始化为NULL,一切都很好。
你能帮忙找出这种混乱的答案吗?非常感谢。
答案 0 :(得分:2)
令人高兴的是,你的线程实际上是异步终止,破坏了StreamX实例。
使用探测器:
struct StreamX
{
StreamX() { puts(__FUNCTION__); }
~StreamX() { puts(__FUNCTION__); }
};
我得到以下输出:
StreamX
0x7f258c0008c0
~StreamX
StreamX
0x7f25740008c0
~StreamX
StreamX
0x7f25840008c0
~StreamX
StreamX
0x7f25780008c0
StreamX
~StreamX
0x7f257c0008c0
~StreamX
real 0m0.002s
user 0m0.000s
sys 0m0.004s
后续分配重用相同的堆地址是有意义的,因为不涉及很多碎片。换句话说,您不能仅仅比较指针以查看它们是否在并发应用程序中为同一对象设置别名。
与第二个例子的区别仅在于虚假。有许多因素可以 - 而且会 - 影响结果。例如。在每个线程结束时添加一个小延迟将删除线程在其他实例被实例化之前终止的所有机会。