2015-06-06 145 views
0

當我嘗試使用mutex與RAII。多線程構造函數和析構函數

class MutexLock 
{ 
public: 
    MutexLock() { 
     pthread_mutex_init(&mutex_, NULL); 
     cout << "construct of MutexLock" << endl; 
    } 
    ~MutexLock() { 
     cout << "deconstruct of MutexLock" << endl; 
     pthread_mutex_destroy(&mutex_); 
    } 

    void lock() { 
     pthread_mutex_lock(&mutex_); 
    } 

    void unlock() { 
     pthread_mutex_unlock(&mutex_); 
    } 

private: 
    MutexLock(const MutexLock &); 
    MutexLock& operator=(const MutexLock &); 

    pthread_mutex_t mutex_; 
}; 

class MutexLockGuard 
{ 
public: 
    explicit MutexLockGuard(MutexLock &mutex): mutex_(mutex) { 
     cout << "construct of MutexLockGuard" << endl; 
     mutex_.lock(); 
    } 
    ~MutexLockGuard() { 
     cout << "deconstruct of MutexLockGuard" << endl; 
     mutex_.unlock(); 
    } 

private: 
    MutexLockGuard(const MutexLock &); 
    MutexLockGuard& operator=(const MutexLock &); 
    MutexLock &mutex_; 
}; 


MutexLock mutex; 
int cnt = 5; 

void *f(void *arg){ 
    long t_num = (long) arg; 
    while(true){ 
     MutexLockGuard lock(mutex); 
     if(cnt>0){ 
      usleep(1); 
      cout << "args: " << t_num << " " << "cnt: " << cnt-- << endl; 
     } 
     else{break;}  
    } 
    return NULL; 
} 

int main() 
{ 
    pthread_t tid, tid1, tid2, tid3; 
    int ret = pthread_create(&tid, NULL, f,(void*)11); 
    if(ret == -1){ 
     perror("create error\n"); 
    } 

    ret = pthread_create(&tid1, NULL, f, (void*)22); 
    if(ret == -1){ 
     perror("create error\n"); 
    } 

    ret = pthread_create(&tid2, NULL, f, (void*)33); 
    if(ret == -1){ 
     perror("create error\n"); 
    } 

    ret = pthread_create(&tid3, NULL, f, (void*)44); 
    if(ret == -1){ 
     perror("create error\n"); 
    } 

    pthread_join(tid, NULL); 
    pthread_join(tid1, NULL); 
    pthread_join(tid2, NULL); 
    pthread_join(tid3, NULL); 
    return 0; 
} 

結果表明作爲

construct of MutexLock 
construct of MutexLockGuard 
construct of MutexLockGuard 
construct of MutexLockGuard 
construct of MutexLockGuard 
args: 11 cnt: 5 
deconstruct of MutexLockGuard 
construct of MutexLockGuard 
args: 11 cnt: 4 
deconstruct of MutexLockGuard 
construct of MutexLockGuard 
args: 11 cnt: 3 
deconstruct of MutexLockGuard 
construct of MutexLockGuard 
args: 11 cnt: 2 
deconstruct of MutexLockGuard 
construct of MutexLockGuard 
args: 11 cnt: 1 
deconstruct of MutexLockGuard 
construct of MutexLockGuard 
deconstruct of MutexLockGuard 
deconstruct of MutexLockGuard 
deconstruct of MutexLockGuard 
deconstruct of MutexLockGuard 
deconstruct of MutexLock 

當創建了四個線程,被創建的MutexLockGuard四個實例。但爲什麼線程args: 11被破壞,而其他三個線程的生命週期與主線程一樣長呢?

+0

你的問題是什麼? 「我不明白」不是一個問題。花更多的時間去理解它,然後帶着一個問題來找我們。我們不是指導或教學服務;這是一個專業的問答!!!!!!!!!!!!! –

+0

inb4是的我知道重複感嘆號的諷刺 –

回答

1

您的代碼正在創建四個線程。

這些線程中的每一個都進入while(true)循環的f(),因此創建一個MutexLockGuard。然後其中一個線程進入互斥鎖,並繼續執行。

所以序列

1)四線程啓動,所有四個創建MutexLockGuard。因此四行construct of MutexLockGuard

2)其中一個線程(首先根據您的輸出創建)成功鎖定互斥鎖,並生成輸出args: 11 cnt: 5

這表明鎖定互斥鎖不一定是瞬間的。 main()線程可能會在其被任何子線程搶佔之前創建所有線程。

1

所有線程構造一個MutexLockGuard但只有一個被允許獲取互斥並繼續(按預期)。

但是,當那個破壞其MutexLockGuard並釋放互斥鎖時,事實證明它會循環並創建一個新的MutexLockGuard並在系統解除阻塞另一個線程並獲取互斥鎖之前獲取該互斥鎖。

互斥量的收購不保證公平。系統可能會這樣做,試圖阻止開銷工作切換線程。

故事的寓意是要小心,不要認爲互斥體會下令。所有你應該承擔互斥體的工作就是防止線程同時執行。

0

這是因爲當線程正在休眠時,它仍然保持互斥體。它在喚醒後纔會解鎖互斥鎖。所以其他線程沒有機會獲得互斥鎖。更改代碼如下,然後再試一次

while(true){  
    if(cnt>0){ 
     usleep(1); 
     {MutexLockGuard lock(mutex); 
     cout << "args: " << t_num << " " << "cnt: " << cnt-- << endl; 
     } 
    } 

    else{break;}  
} 
相關問題