多线程中的构造函数和析构函数

时间:2015-06-06 03:07:46

标签: c++ multithreading raii

当我尝试将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被破坏而其他三个线程的生命周期与主线程一样长?

3 个答案:

答案 0 :(得分:1)

您的代码正在创建四个线程。

这些线程中的每一个都进入while(true)中的f()循环,因此会创建MutexLockGuard。然后其中一个线程进入互斥锁,然后继续执行。

所以序列是

1)启动了四个线程,所有四个线程都创建了一个MutexLockGuard。因此四行construct of MutexLockGuard

2)其中一个线程(根据您的输出创建的第一个)成功锁定互斥锁,并生成输出args: 11 cnt: 5

这表明锁定互斥锁不一定是瞬时的。 main()线程可能会在被任何子线程抢占之前创建所有线程。

答案 1 :(得分:1)

所有线程构造一个MutexLockGuard,但只允许一个获取互斥锁并继续(按预期)。

但是,当那个销毁MutexLockGuard并释放互斥锁时,它会循环并创建一个新的MutexLockGuard并在系统解除阻塞另一个线程之前获取互斥锁并允许它们获得互斥锁。

Mutex的收购并不保证是公平的。系统可能会这样做,以防止支出工作切换线程。

故事的寓意是要小心不要假设互斥体会命令。你应该假设互斥体所做的就是阻止线程同时执行。

答案 2 :(得分:0)

这是因为当线程处于休眠状态时,它仍然保留了互斥锁。它只会在唤醒后解锁互斥锁。因此其他线程没有机会获得互斥锁。更改代码如下,然后重试

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

    else{break;}       
}