Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СРВ_12_22_01_Механизмы_синхронизации.pptx
Скачиваний:
4
Добавлен:
20.06.2023
Размер:
163.67 Кб
Скачать

Семафоры (POSIX)

Неименованные семафоры

#include <semaphore.h> (sem_t mySem;)

int sem_init( sem_t* sem, int pshared, unsigned value );

*sem – указатель на объект, который мы хотим инициировать pshared – не «0», если мы хотим, чтобы sem разделялся процессами через

разделяемую память

value – значение семафора (> 0, если «0», то семафор блокирован)

int sem_destroy( sem_t * sem ); int sem_wait( sem_t * sem );

int sem_post( sem_t * sem ) инкремент значения семафора;

int sem_trywait( sem_t * sem ) - неблокирующий декремент значения семафора, возвращает значение счетчика

Именованные семафоры – межпроцессная и сетевая поддержка; примитивы другие.

12. Механизмы синхронизации

2015 v.01

11

Мьютекс (mutual exclusion)

Class Семафор {

Очередь: УказательНаОчередьЗаблокированных НачЗначение: 0..N; (*)

ТекЗначение: 0..M; (*) P(); V();

}

(*) Для двоичного семафора - 0..1

mutex {

Очередь: УказательНаОчередьЗаблокированных boolean: занят, свободен;

Задача: владелец;

lock(); unlock(); //неделимые операции

}

12. Механизмы синхронизации

2015 v.01

12

Попытка вызова unlock() «не владельцем»

Приложение

Создать_Mutex(S);

Задача 1

 

Задача 2

 

Задача 3

S.lock();

 

S.lock();

 

S.unlock();

КС1

 

КС2

 

 

 

 

S.unlock();

 

S.unlock();

 

 

 

 

 

 

 

Задача 1 - владелец

Бросается

t

 

 

Исключение

t

 

 

Задача 2 – становиться владельцем

 

 

Задача 3 – Ошибка!

 

t

 

 

12. Механизмы синхронизации

13

Мьютекс - инициализация и захват

TCB-владелец

Создать_mutex(mutex S):

 

 

 

 

 

 

1.

S = new mutex();

 

 

 

2.

S.Очередь = СоздатьОчередь();

 

Приоритет

 

3.

S.Владелец = nill;

 

 

 

ТПриоритет

 

4.

S.Состояние = свободен;

 

 

lock():

 

 

 

 

TCB- ТекПроц

1.

Запретить_Прерывания;

 

 

 

 

2.if(Состояние==занят) then

2.1.Владелец.ТПриоритет = ТекПроц.Приоритет;

2.2.ждать(Состояние==свободен);

3.Владелец = ТекПроц;

4.Состояние = занят;

5.Разрешить_Прерывания;

действие 2.1. – приоритет ТекПроц будет выше приоритета Владелец; иначе ТекПроц не мог бы вытеснить владельца и вызвать loc()

12. Механизмы синхронизации

2015 v.01

14

Освобождение

unlock();

1.Запретить_Прерывания;

2.if(Владелец==ТекПроц) then

2.1.R = Взять_Из_Очереди(Очередь);

2.2.Поставить_В_Очередь(R,ОчердьГотовых)

2.3.Состояние = свободен;

else Исключение; // Еще одна особенность

3.Владелец.ТПриоритет = Владелец.Приоритет;

4.Владелец = nill;

5.Разрешить_Прерывания();

12. Механизмы синхронизации

2015 v.01

15

 

Мьютекс QNX (POSIX)

struct pthread_mutex_attr_t {

int protocol;

pthread_mutex_init(…)

int prioceiling;

pthread_mutex_lock(…)

unsigned owner;

pthread_mutex_unlock(…)

. . .

 

}

pthread_mutexattr_setprotocol(.., int protocol) protocol - PTHREAD_PRIO_INHERIT, PTHREAD_PRIO_PROTECT int pthread_mutexattr_getprotocol(…)

pthread_mutexattr_setprioceiling(.., int prioceiling)

int pthread_mutexattr_getprioceiling(.., int prioceiling) рrioceiling – приоритет, присваиваемый потоку,

захватившему мьютекс (см. слайд 7, struct sched_param)

12. Механизмы синхронизации

2015 v.01

16

Мьютекс QNX (POSIX)

#include <pthread.h> (pthread_mutex_t mutex;)

int sem_init(pthread_mutex_t* mutex, pthread_mutex_attr* attr);

*mutex – указатель на объект, который мы хотим инициировать *attr – ссылка на структуру атрибутов

int pthread_mutex_destroy(pthread_mutex_t* mutex); int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex); -

пытается захватить мьютекс, а если он уже занят, то выполнение продолжается без блокировки потока

int pthread_mutex_unlock(pthread_mutex_t *mutex);

#include <time.h>

int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec* abs_timeout);

блокировка прекращается по истечению времени

12. Механизмы синхронизации

2015 v.01

17

Мьютекс и инверсия приоритетов

struct

_sync_attr_t {

#include <sched.h>

int

protocol;

 

int

flags;

struct sched_param {

int

prioceiling;

int32_t sched_priority;

int

clockid;

int32_t sched_curpriority;

int

reserved[4];

. . .

}

 

}

pthread_mutexattr_setprotocol(pthread_mutexattr_t* attr, int protocol)

int pthread_mutexattr_getprotocol(…)

protocol:

PTHREAD_PRIO_INHERIT,(по умолчанию)

PTHREAD_PRIO_PROTECT pthread_mutexattr_setprioceiling(.., int prioceiling)

int pthread_mutexattr_getprioceiling(.., int prioceiling)

рrioceiling – приоритет, присваиваемый потоку, захватившему мьютекс

12. Механизмы синхронизации 2015 v.01

18

Условные переменные

#include <pthread.h>

int pthread_cond_init( pthread_cond_t* cond, pthread_condattr_t* attr );

int pthread_cond_destroy( pthread_cond_t* cond); int pthread_cond_broadcast( pthread_cond_t* cond);

 

Поток А захватывает

Поток А

мьютекс

 

Поток А блокируется на УП

pthread_mutex_lock(&m);

 

и освобождает мьютекс

. . .

while (!arbitrary_condition){

Поток В «посылает сигнал»

pthread_cond_wait(&cv, &m);

 

и освобождает мьютекс

}

Поток А разблокируется,

. . .

 

захватывает мьютекс и

pthread_mutex_unlock(&m);

 

 

 

ставится в очередь

 

Поток В

«готовых»

 

Поток А продолжает

 

pthread_cond_signal(&cv);

 

 

выполнение и освобождает

 

 

12. Механизмы синхронизации

2015 v.01

мьютекс

19

 

Механизм сообщений (QNX)

Клиент Сервер

2 MsgReceive

Блокировка

1 MsgSend

Блокировка

3 MsgReply

Клиент

. . .

int coid;

coid = ConnectAttach(0, getpid(), chid, 0, 0); /* Готовим сообщение */

MsgSend(coid, smsg, sizeof(smsg),

rmsg, sizeof(rmsg));

/* Обрабатываем ответ */

. . .

Сервер

int chid;

chid = ChannelCreate(0);

. . .

for (;;){

rcvid = MsgReceive(chid, &rmsg, sizeof(msg), NULL);

/* Обрабатываем сообщение */ MsgReply(rcvid, EOK, &smsg, sizeof(msg));

. . .

}

12. Механизмы синхронизации

2015 v.01

20