2014-04-01 71 views
1

//代碼段1thread_specific_ptr多線程混亂

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 

//代碼段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時,所有接縫都很好。

請您幫忙弄清楚這個困惑的答案嗎?非常感謝。

回答

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 

是有意義的後續分配重複使用同一個堆地址,因爲沒有涉及太多碎片。換句話說,你不能只比較指針來查看它們是否在併發應用程序中使用同一個對象。

與第二個例子的區別只是僞造的。有許多因素會影響結果。例如。在每個線程末尾添加一個微小的延遲將在其他實例實例化之前消除線程終止的所有機會。

看到它Live On Coliru

+0

總是高興地看到你的答案。 –