2015-06-06 4 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

Что вы хотите сказать? «Я не понимаю», это не вопрос. Потратьте больше времени на понимание, а затем приходите к нам с вопросом. Мы не являемся наставниками или преподавателями; это профессиональный Q & A !!!!!!!!!!!!! –

+0

inb4 да, я знаю об иронии повторяющихся восклицательных знаков –

ответ

1

Ваш код создает четыре потока.

Каждый из этих нитей входит в петлю while(true) в f() и поэтому создает MutexLockGuard. Затем один из потоков входит в мьютекс, и выполнение продолжается.

Таким образом, последовательность

1) Четыре темы, и все четыре создать MutexLockGuard. Отсюда четыре линии: construct of MutexLockGuard.

2) Один из потоков (первый, созданный в соответствии с вашим выходом) успешно блокирует мьютекс и производит выход args: 11 cnt: 5.

Это демонстрирует, что блокировка мьютекса не обязательно мгновенно. Поток main(), возможно, создает все потоки, прежде чем он будет выгружен любым из его дочерних потоков.

1

Все потоки создают MutexLockGuard, но только один разрешается приобретать мьютексы и продолжать (как и предполагалось).

Однако, когда этот один разрушает его MutexLockGuard и освобождает мьютекс, то получается, что петли вокруг и создает новый MutexLockGuard и приобретает мьютекс, прежде чем система разблокирует другой поток и позволяет им получить мьютекс.

Приобретение Mutex не гарантируется. Система может вести себя так, пытаясь предотвратить трассировку рабочих потоков.

Мораль этой истории заключается в том, чтобы быть осторожным, чтобы не предполагать, что мьютексы будут заказывать вещи. Все, что вы должны принять, мьютексы будут делать, это предотвращать выполнение потоков одновременно.

0

Это потому, что когда нить спала, она по-прежнему удерживает мьютекс. Он только разблокирует мьютекс после его пробуждения. Таким образом, у других потоков нет возможности получить мьютекс. Измените код следующим образом и повторите попытку

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

    else{break;}  
} 

 Смежные вопросы

  • Нет связанных вопросов^_^