pthread_mutex_init(3)

NUME
pthread_mutex_init, pthread_mutex_lock, pthread_mutex_trylock, pthread_mutex_unlock, pthread_mutex_destroy - operații asupra mutex-urilor

SINOPSIS
#include <pthread.h>

pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;

int pthread_mutex_init(pthread_mutex_t *mutex,
                       const pthread_mutexattr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);

DESCRIERE
Un mutex este un dispozitiv de EXCLUDERE MUTUALĂ „MUTual EXclusion” și este util pentru protejarea structurilor de date partajate împotriva modificărilor simultane și pentru implementarea secțiunilor critice și a monitorizărilor.

Un mutex are două stări posibile: deblocat (nu este deținut de niciun fir) și blocat (este deținut de un singur fir). Un mutex nu poate fi niciodată deținut simultan de două fire diferite. Un fir care încearcă să blocheze un mutex care este deja blocat de un alt fir este suspendat până când firul proprietar deblochează primul mutex.

pthread_mutex_init() inițializează obiectul mutex indicat de mutex în conformitate cu atributele mutex specificate în mutexattr. În cazul în care mutexattr este NULL, se utilizează în schimb atributele implicite.

Implementarea LinuxThreads acceptă doar un singur atribut mutex, mutex kind, care este fie „fast”, „recursive”, fie „error checking”. Tipul unui mutex determină dacă acesta poate fi blocat din nou de un fir care îl deține deja. Tipul implicit este „fast”. A se vedea pthread_mutexattr_init(3) pentru mai multe informații despre atributele mutex-urilor.

Variabilele de tip pthread_mutex_t pot fi, de asemenea, inițializate static, utilizând constantele PTHREAD_MUTEX_INITIALIZER (pentru mutex-uri rapide), PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP (pentru mutex-uri recursive) și PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP (pentru mutex-uri de verificare a erorilor).

pthread_mutex_lock() blochează mutex-ul dat. Dacă mutex-ul este în prezent deblocat, acesta devine blocat și este deținut de firul apelant, iar pthread_mutex_lock() returnează imediat. Dacă mutex-ul este deja blocat de un alt fir de execuție, pthread_mutex_lock() suspendă firul apelant până când mutex-ul este deblocat.

În cazul în care mutex-ul este deja blocat de firul apelant, comportamentul lui pthread_mutex_lock() depinde de tipul mutex-ului. În cazul în care mutex-ul este de tipul „fast”, firul apelant este suspendat până când mutex-ul este deblocat, ceea ce duce efectiv la blocarea firului apelant. În cazul în care mutex-ul este de tipul „error checking”, pthread_mutex_lock returnează imediat cu codul de eroare EDEADLK. În cazul în care mutex-ul este de tip „recursive”, pthread_mutex_lock() reușește și returnează imediat, înregistrând numărul de blocări ale mutex-ului de către firul apelant. Un număr egal de operații pthread_mutex_unlock() trebuie efectuate înainte ca mutex-ul să revină la starea deblocată.

pthread_mutex_trylock() se comportă în mod identic cu pthread_mutex_lock(), cu excepția faptului că nu blochează firul apelant dacă mutex-ul este deja blocat de un alt fir (sau de firul apelant în cazul unui mutex „fast”). În schimb, pthread_mutex_trylock() returnează imediat cu codul de eroare EBUSY.

pthread_mutex_unlock() deblochează mutex-ul dat. Se presupune că mutex-ul este blocat și deținut de firul apelant la intrarea în pthread_mutex_unlock(). În cazul în care mutex-ul este de tip „fast”, pthread_mutex_unlock() îl readuce întotdeauna în starea deblocată. În cazul în care este de tip „recursive”, descrește numărul de blocaje ale mutex-ului (numărul de operații pthread_mutex_lock() efectuate asupra acestuia de către firul apelant) și numai atunci când acest număr ajunge la zero, mutex-ul este efectiv deblocat.

În cazul mutex-urilor „error checking” și „recursive”, pthread_mutex_unlock() verifică de fapt în timpul execuției dacă mutex-ul este blocat la intrare și dacă a fost blocat de același fir care apelează acum pthread_mutex_unlock(). În cazul în care aceste condiții nu sunt îndeplinite, se returnează un cod de eroare, iar mutex-ul rămâne neschimbat. Mutex-urile „fast” nu efectuează astfel de verificări, permițând astfel ca un mutex blocat să fie deblocat de către un alt fir de execuție decât proprietarul său. Acesta este un comportament neportabil și nu trebuie să se bazeze pe el.

pthread_mutex_destroy() distruge un obiect mutex, eliberând resursele pe care le-ar putea deține. Mutex-ul trebuie să fie deblocat la intrare. În implementarea LinuxThreads, nicio resursă nu este asociată cu obiectele mutex, astfel încât pthread_mutex_destroy() nu face de fapt nimic, cu excepția verificării faptului că mutex-ul este deblocat.

ANULARE
Niciuna dintre funcțiile mutex nu este un punct de anulare, nici măcar pthread_mutex_lock(), în ciuda faptului că poate suspenda un fir de execuție pentru durate arbitrare. În acest fel, starea mutex-urilor la punctele de anulare este previzibilă, permițând operatorilor de anulare să deblocheze exact acele mutex-uri care trebuie deblocate înainte ca firul să se oprească din execuție. În consecință, firele care utilizează anularea amânată nu ar trebui să dețină niciodată un mutex pentru perioade lungi de timp.

SIGURANȚA SEMNALELOR ASINCRONE
Funcțiile mutex nu sunt sigure pentru semnalul asincron. Acest lucru înseamnă că nu trebuie apelate de la un gestionar de semnal. În special, apelarea funcțiilor pthread_mutex_lock() sau pthread_mutex_unlock() de la un gestionar de semnal poate bloca firul apelant.

VALOAREA RETURNATĂ
pthread_mutex_init() returnează întotdeauna 0. Celelalte funcții mutex returnează 0 în caz de succes și un cod de eroare diferit de zero în caz de eroare.

ERORI-IEȘIRE
Funcția pthread_mutex_lock() returnează următorul cod de eroare în caz de eroare:

    EINVAL
        Mutex-ul nu a fost inițializat corespunzător.

    EDEADLK
        Mutex-ul este deja blocat de firul apelant (numai mutex-urile „error checking”).

Funcția pthread_mutex_trylock() returnează următoarele coduri de eroare în caz de eroare:

    EBUSY
        Mutex-ul nu a putut fi achiziționat deoarece era blocat în prezent.

    EINVAL
        Mutex-ul nu a fost inițializat corespunzător.

Funcția pthread_mutex_unlock() returnează următorul cod de eroare în caz de eroare:

    EINVAL
        Mutex-ul nu a fost inițializat corespunzător.

    EPERM
        Firul apelant nu deține mutex-ul (numai mutex-urile „error checking”).

Funcția pthread_mutex_destroy() returnează următorul cod de eroare în caz de eroare:

    EBUSY
        Mutex-ul este blocat în prezent.

CONSULTAȚI ȘI
pthread_mutexattr_init(3), pthread_mutexattr_setkind_np(3), pthread_cancel(3).

EXEMPLU
O variabilă globală partajată x poate fi protejată de un mutex după cum urmează:

    int x; pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;

Toate accesările și modificările la x trebuie să fie între paranteze prin apeluri la pthread_mutex_lock() și pthread_mutex_unlock() după cum urmează:

    pthread_mutex_lock(&mut); /* operează pe x */ pthread_mutex_unlock(&mut);

TRADUCERE
Traducerea în limba română a acestui manual a fost făcută de Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>

Această traducere este documentație gratuită; citiți Licența publică generală GNU Versiunea 3 (https://www.gnu.org/licenses/gpl-3.0.html) sau o versiune ulterioară cu privire la condiții privind drepturile de autor. NU se asumă NICIO RESPONSABILITATE.

Dacă găsiți erori în traducerea acestui manual, vă rugăm să trimiteți un e-mail la translation-team-ro@lists.sourceforge.net.