Опубликован: 06.12.2004 | Доступ: свободный | Студентов: 1087 / 122 | Оценка: 4.76 / 4.29 | Длительность: 20:58:00
ISBN: 978-5-9556-0021-5
Лекция 2:

Средства синхронизации потоков управления

Мьютексы

Функции, обслуживающие мьютексы, можно разбить на следующие группы:

  • инициализация и разрушение мьютексов: pthread_mutex_init(), pthread_mutex_destroy() (см. листинг 2.1);
    #include <pthread.h>
    
    int pthread_mutex_init (
        pthread_mutex_t *restrict mutex, 
        const pthread_mutexattr_t
            *restrict attr);
    
    int pthread_mutex_destroy (
        pthread_mutex_t *mutex);
    
    pthread_mutex_t mutex =
        PTHREAD_MUTEX_INITIALIZER;
    Листинг 2.1. Описание функций инициализации и разрушения мьютексов.
  • захват и освобождение мьютексов: pthread_mutex_lock(), pthread_mutex_trylock(), pthread_mutex_timedlock(), pthread_mutex_unlock() (см. листинги 2.2 и 2.3);
    #include <pthread.h>
    
    int pthread_mutex_lock (
        pthread_mutex_t *mutex);
    
    int pthread_mutex_trylock (
        pthread_mutex_t *mutex);
    
    int pthread_mutex_unlock (
        pthread_mutex_t *mutex);
    Листинг 2.2. Описание функций захвата и освобождения мьютексов.
    #include <pthread.h>
    #include <time.h>
    int pthread_mutex_timedlock (
        pthread_mutex_t *restrict mutex,
        const struct
            timespec *restrict abstime);
    Листинг 2.3. Описание функции захвата мьютексов с ограниченным ожиданием.
  • опрос и установка атрибутов мьютекса: pthread_mutex_getprioceiling(), pthread_mutex_setprioceiling() (см. листинг 2.4);
    #include <pthread.h>
    
    int pthread_mutex_getprioceiling (
        const pthread_mutex_t 
        *restrict mutex,
        int *restrict prioceiling);
    
    int pthread_mutex_setprioceiling (
        pthread_mutex_t 
        *restrict mutex, int prioceiling, 
        int *restrict old_ceiling);
    Листинг 2.4. Описание функций опроса и установки атрибутов мьютекса.
  • инициализация и разрушение атрибутных объектов мьютексов: pthread_mutexattr_init(), pthread_mutexattr_destroy() (см. листинг 2.5);
    #include <pthread.h>
    
    int pthread_mutexattr_init (
        pthread_mutexattr_t *attr);
    
    int pthread_mutexattr_destroy (
        pthread_mutexattr_t *attr);
    Листинг 2.5. Описание функций инициализации и разрушения атрибутных объектов мьютексов.
  • опрос и установка атрибутов мьютекса в атрибутных объектах: pthread_mutexattr_gettype(), pthread_mutexattr_settype(), pthread_mutexattr_getpshared(), pthread_mutexattr_setpshared(), pthread_mutexattr_getprotocol(), pthread_mutexattr_setprotocol(), pthread_mutexattr_getprioceiling(), pthread_mutexattr_setprioceiling() (см. листинг 2.6).
    #include <pthread.h>
    
    int pthread_mutexattr_gettype (
        const pthread_mutexattr_t
            *restrict attr, 
        int *restrict type);
    
    int pthread_mutexattr_settype (
        pthread_mutexattr_t *attr, int type);
    
    int pthread_mutexattr_getpshared (
        const pthread_mutexattr_t
            *restrict attr, 
        int *restrict pshared);
    
    int pthread_mutexattr_setpshared (
        pthread_mutexattr_t *attr,
        int pshared);
    
    int pthread_mutexattr_getprotocol (
        const pthread_mutexattr_t
            *restrict attr, 
        int *restrict protocol);
    
    int pthread_mutexattr_setprotocol (
        *attr, int protocol);
    
    int pthread_mutexattr_getprioceiling (
        const pthread_mutexattr_t
            *restrict attr, 
        int *restrict prioceiling);
    int pthread_mutexattr_setprioceiling (
        pthread_mutexattr_t *attr,
        int prioceiling);
    Листинг 2.6. Описание функций опроса и установки атрибутов мьютекса в атрибутных объектах.

Мы не будем детально описывать каждую из перечисленных выше функций (хотя бы потому, что дисциплина работы с атрибутами и атрибутными объектами та же, что и для потоков управления ), но коснемся лишь отдельных, специфических аспектов.

Сразу после инициализации функцией pthread_mutex_init() мьютекс, разумеется, оказывается свободным. Разрушить функцией pthread_mutex_destroy() можно только инициализированный, свободный мьютекс.

Для инициализации статически описанных мьютексов с подразумеваемыми значениями атрибутов целесообразно воспользоваться макросом PTHREAD_MUTEX_INITIALIZER. Эффект будет тем же, что и после вызова pthread_mutex_init() с пустым указателем в качестве значения аргумента attr, только без накладных расходов на проверку корректности атрибутного объекта.

В стандарте POSIX-2001 тип pthread_mutex_t трактуется как абстрактный, со скрытой структурой и даже без методов для присваивания и сравнения на равенство, а попытки обойти их отсутствие за счет применения операций с областями памяти, естественно, обречены на неудачу поскольку, согласно стандарту, для синхронизации должны использоваться сами объекты- мьютексы, а не их копии. Это "развязывает руки" операционной системе в использовании доступных аппаратных возможностей при реализации мьютексов, делая ее максимально эффективной.

У инициализированного мьютекса имеется четыре атрибута:

  • тип (обслуживается функциями pthread_mutexattr_gettype() и pthread_mutexattr_settype() );
  • верхняя грань приоритетов выполнения (функции pthread_mutex_getprioceiling(), pthread_mutex_setprioceiling(), pthread_mutexattr_getprioceiling(), pthread_mutexattr_setprioceiling() );
  • протокол ( pthread_mutexattr_getprotocol(), pthread_mutexattr_setprotocol() );
  • признак использования несколькими процессами ( pthread_mutexattr_getpshared(), pthread_mutexattr_setpshared() ).

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

Владимир Крюков
Владимир Крюков
Казахстан