Мьютекс
Мьютекс - инструмент, предназначенный для решения задач синхронизации доступа к разделяемым ресурсам на основе организации взаимного исключения.
Открыть мьютекс может только та нить, которая его закрыла. Если попытаться из другой нити, возникнет ошибка.
В этом заключается разница между семафорами и мьютексами.
У мьютекса нет значения, но есть состояние открыт/закрыт. В этом отличие от семафора Дейкстры.
Init
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)mutex- указатель на переменную типа мьютекс.attr- атрибуты мьютекса (не рассматриваем. Будет только NULL - атрибуты по умолчанию)
pthread_ функции возвращают 0, в случае успеха, и код ошибки, в случае неудачи. Init возвращает только 0.
Destroy
int pthread_mutex_destroy(pthread_mutex_t *mutex)Завершение работы с мьютексом до освобождения динамической памяти.
В мане написано, что в линуксовой реализации с мьютексом не ассоциировано ресурсов машины, поэтому destroy ничего не делает, за исключением проверки занятости.
Lock
int pthread_mutex_lock(pthread_mutex_t *mutex)Закрывает указанный мьютекс. Если тот уже закрыт, процесс блокируется до тех пор, пока не получится закрыть мьютекс.
Если закрыть мьютекс из одной нити дважды, нить получит deadlock. (при NULL параметре в init)
Trylock
int pthread_mutex_trylock(pthread_mutex_t *mutex)То же, что и обычный lock, но возвращает код ошибки EBUSY, если мьютекс уже закрыт.
Unlock
int pthread_mutex_unlock(pthread_mutex_t *mutex)Освобождает указанный мьютекс. Можно сделать только из нити, занявшей его. Если попытаться из другой нити, вернётся ошибка. (при NULL в init)
Пример
Создаём 10 нитей.
Разделяемый ресурс - строка: каждая нить определяет текущую длину строки и добавляет код символа с возрастающим значением в её конец.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#define N_SIZE 10
char str[N_SIZE + 1];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// macros from pthread.h
void *fThread(void *arg) {
pthread_mutex_lock(&mutex);
// add symbol
int iPos = strlen(str);
str[iPos] = 'A' + iPos;
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t threads[N_SIZE];
int i;
// init array by zeros
memset(str, 0, N_SIZE + 1);
for (i = 0; i < N_SIZE; i++) {
pthread_create(&threads[i], NULL, fThread, NULL);
}
// waiting for threads end
for (i = 0; i < N_SIZE; i++) {
pthread_join(threads[i], NULL);
}
printf("%s\n", str);
return 0;
}