Operacje na mutexach

pthread_mutex_init, pthread_mutex_lock, pthread_mutex_trylock,

pthread_mutex_unlock, pthread_mutex_destroy

Deklaracja

#include <pthread.h>

pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_t recmutex =

PTHREAD_RECURSIVE_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);

Opis

Mutex jest mechanizmem wzajemnego wykluczania (MUTual EXclusion) sluzacym do chronienia danych dzielonych miedzy watkami przed rownoczesnymi modyfikacjami i uzywanym do implementacji sekcji krytycznych i monitorow.

Mutex ma dwa mozliwe stany: otwarty (nie zajety przez zaden watek) lub zajety (przez jeden watek). Mutex nie moze byc w posiadaniu wiecej niż jednego watku na raz. Watek probujacy zajac mutex bedacy w osiadaniu innego watku jest zawieszany az do chwili zwolnienia mutexu przez watek, ktory go posiadal wczesniej.

Funkcja pthread_mutex_init inicjalizuje obiekt mutex zgodnie z atrybutami przekazanymi przez mutexattr. Jesli mutexattr jest NULL uzywane sa wartosci domyslne. Funkcja zawsze zwraca 0.

Funkcja pthread_mutex_lock zajmuje dany mutex. Jesli mutex jest wolny zostaje zajety i przypisany watkowi wolajacemu i pthread_mutex_lock konczy dzialanie natychmiast. Jesli mutex jest zajety przez jakis inny watek pthread_mutex_lock zawiesza dzialanie watku az do momentu, kiedy mutex zostanie zwolniony.

Jesli mutex jest juz zajety przez watek wolajacy to zachowanie funkcji zalezy od rodzaju mutexu. Jesli mutex dopusza rekurencje to funkcja konczy dzialanie poprawnie zapisujac sobie ilosc wywolan funkcji (glebokosc rekurencji - potem trzeba wywolac tyle samo razy pthread_mutex_unlock zeby zwolnic mutex), jesli zas nie dopuszcza to doprowadza do blokady (deadlock) watku. Funkcja zwraca blad EINVAL jesli mutex nie zostal wczesniej poprawnie zainicjalizowany.

Funkcja pthread_mutex_trylock zachowuje sie identyczne do pthread_mutex_lock, jednak nie jest blokujaca (zwraca EBUSY w razie zajetosci mutexu).

Funkcja pthread_mutex_unlock zwalnia dany mutex. Mutex musi byc wczesniej zajety przez wolajacy proces. Jesli mutex jest nierekurencyjny to zawsze wraca do stanu zwolnionego, jesli jest rekurencyjny, to zminiejszana jest glebokosc rekurencji w mutexie. Jedynie gdy glebokosc jest zero mutex zostaje faktycznie zwolniony. Funkcja zwraca blad EINVAL jesli mutex nie zostal wczesniej poprawnie zainicjalizowany.

Funkcja pthread_mutex_destroy niszczy obiekt mutexu i zwalnia zasoby z nim zwiazane. Mutex musi byc wolny wpp zwracana jest wartosc EBUSY.

Zadna z funkcji obslugujacych mutexy nie jest cancellation point i zadna nie powinna byc wykonywana z funkcji obslugi sygnalu (nie jest async-signal safe).

Przyklad:

Zmienna dzielona x moze byc w nastepujacy sposob chroniona przez mutex:

int x;

pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;

Wszystkie operacje na zmiennej x powinny byc otoczone wywolaniami pthread_mutex_lock i pthread_mutex_unlock:

pthread_mutex_lock(&mut);

/* operacje na x */

pthread_mutex_unlock(&mut);