2015-06-06 80 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;}  
} 
相关问题