2011-01-05 2 views
6

Извините за мой английский - я русский.Блокировка мьютекса в одной теме и разблокировка его в другом

Будет ли этот код правильным и портативным?

void* aThread(void*) 
{ 
    while(conditionA) 
    { 
     pthread_mutex_lock(mutex1); 
     //do something 
     pthread_mutex_unlock(mutex2); 
    } 
} 

void* bThread(void*) 
{ 
    while(conditionB) 
    { 
     pthread_mutex_lock(mutex2); 
     //do something 
     pthread_mutex_unlock(mutex1); 
    } 
} 

Фактически в целевом приложении У меня есть три потока - два для записи массива и один для чтения. И мне нужно, чтобы сразу после того, как один из потоков изменил массив, третий поток отображает содержимое массива.

ответ

10

Это не так. Если поток A попадает в mutex_unlock (2), прежде чем поток B попадает в mutex_lock (2), вы сталкиваетесь с неопределенным поведением. Вы также не должны разблокировать мьютексы другого потока.

pthread_mutex_lock Open Group Base Specification говорит так:

Если тип мьютекс PTHREAD_MUTEX_NORMAL [...] Если поток попытается разблокировать мьютекс, что он не заблокирован или мьютекс, который отпирается, неопределенные результаты поведения.

+0

Хорошо. Но как насчет разблокировки мьютекса, который был заблокирован в другом потоке? Неопределенное поведение? –

+4

Как говорится: «если поток пытается разблокировать мьютекс, который он не заблокировал ... UB» – user562374

3

Как user562734's answer says, ответ нет - вы не можете разблокировать нить, которая была заблокирована другим потоком.

Для достижения требуемой синхронизации считывателя/записи вы должны использовать переменные состояния - pthread_cond_wait(), pthread_cond_signal() и связанные с ними функции.

+0

Семафоры также иногда полезны для ситуаций, когда вы хотите иметь возможность «разблокировать блокировку другого потока». Они на самом деле являются отличным обходным путем для того, что документированное рекомендуемое использование 'pthread_atfork' вызывает неопределенное поведение. :-) –

0

Некоторые реализации позволяют блокировать и разблокировать нити до .

#include <iostream> 
#include <thread> 
#include <mutex> 

using namespace std; 

mutex m; 

void f() {m.lock(); cout << "f: mutex is locked" << endl;} 

void g() {m.unlock(); cout << "g: mutex is unlocked" << endl;} 

main() 
{ 
     thread tf(f); /* start f       */ 
     tf.join();  /* Wait for f to terminate   */ 
     thread tg(g); /* start g       */ 
     tg.join();  /* Wait for g to terminate   */ 
} 

Эта программа печатает

F: мьютекс заблокированные г: мьютекс разблокированы

System является Debian Linux, GCC 4.9.1. -std = C++ 11.

+0

Говорит ли об этом gcc 4.9.1 явно? Если нет, и вы получили свой ответ только из экспериментов, то это все еще UB, хотя в этом случае он работает. –