2017-03-15 32 views
0

確保在多線程環境中僅對堆棧分配的pthread_mutex_t對象進行一次初始化的建議/標準方法是什麼?如何確保共享堆棧分配pthread_mutex_t的單個初始化? (C++)

pthread_mutex_init()手冊頁說:

試圖初始化在 不確定的行爲已初始化互斥結果。

我有一個.cpp文件被編譯到共享庫。此文件的簡化是:

#include <pthread.h> 

static pthread_mutex_t g_mutex; 

int initialize() 
{ 
    pthread_mutex_init(&g_mutex, NULL); 
    pthread_mutex_lock(&g_mutex); 
    // Do init stuff. 
    pthread_mutex_unlock(&g_mutex); 
    return 0; 
} 

initialize()可以在多線程環境中調用。因此,如上所述,pthread_mutex_init()可能會在同一個對象上被調用多次,這是未定義的行爲。所以這需要線程安全......通過使用另一個互斥體。但是,那麼誰是以線程安全的方式初始化這個互斥鎖呢?

在全球範圍內(即與pthread_mutex_t對象聲明相同的範圍)調用pthread_mutex_init()是否合法?是否被認爲是這種情況的「正確」解決方案?

#include <pthread.h> 

static pthread_mutex_t g_mutex; 
static int g_res = pthread_mutex_init(&g_mutex, NULL); 

int initialize() 
{ 
    // g_mutex already initialized (?) so no need to do so here. 
    pthread_mutex_lock(&g_mutex); 
    // Do init stuff. 
    pthread_mutex_unlock(&g_mutex); 
    return 0; 
} 

我已經試過

我編譯和運行第二個代碼塊,這兩者的成功。

但是我還是想問的社區,因爲我有點不清楚停靠全球範圍內pthread_mutex_init()功能的合法性,我想,以確保執行不只是出現的,因爲不確定的工作行爲。

回答

1

是合法的,在全球範圍內調用pthread_mutex_init()(即在同一範圍爲pthread_mutex_t對象的聲明)作爲下方,這被認爲是「正確的」解決方案?

它在C中不合法,但在C++中沒有問題。既然你初始化具有默認屬性的互斥體,然而,這將是最好使用初始化宏:

static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; 
+0

我也讀了關於'PTHREAD_MUTEX_INITIALIZER',但那麼提示問題_什麼,如果默認屬性不會做?_。我也很好奇,會發生什麼在C編譯器中的「解決方案」代碼?是一個編譯或運行時錯誤嗎? – StoneThrow

+0

@StoneThrow,建議的解決方案將被符合C編譯器拒絕 –

+0

「但它在C++中沒有問題」...所以我猜想在C++中,如果默認屬性不行,那麼靜態聲明一個'pthread_mutexattr_t'並將其作爲參數傳遞給'pthread_mutex_init()'...的全局函數是可以接受的。我很好奇這種情況在C中如何解決。也許我會問一個單獨的問題。 – StoneThrow

1
static int g_res = pthread_mutex_init(&g_mutex, NULL); 

是在C++代碼罰款,但在C代碼不工作(是的,你的代碼是純C++,但有人會嘗試在C ...)

對於C(或替代在每the POSIX standard C++):

...

在默認互斥屬性是適當的情況下,宏 PTHREAD_MUTEX_INITIALIZER可用於初始化互斥。 效果應該等同於通過調用 pthread_mutex_init()並將參數attr指定爲NULL來動態初始化。 ...

像這樣:

static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; 
+0

同樣的問題,以@JohnBollinger: \t 我讀到PTHREAD_MUTEX_INITIALIZER爲好,但隨後那會提示這個問題,如果默認屬性不行?我也很好奇,C編譯器中的「解決方案」代碼會發生什麼?這是一個編譯或運行時錯誤? – StoneThrow

+1

@StoneThrow在這種情況下,我會做的是將我的互斥體初始化代碼放在我知道的地方*它只能被調用一次(例如,共享對象初始化函數,當共享對象被加載時只運行一次,或者我會使用一個用'PTHREAD_MUTEX_INITIALIZER'初始化的靜態互斥體來保護我更復雜的初始化代碼。FWIW,Linux提供了可用於初始化其他非默認互斥體的擴展,例如'PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP'。請參見http:// elias .rhi.hi.is/libc/Mutexes.html –