Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Laba_5.doc
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
98.82 Кб
Скачать

2. Семафоры для синхронизации потоков

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

Каждый семафор содержит неотрицательное целое значение. Любой поток может изменять значение семафора. Когда поток пытается уменьшить значение семафора, происходит следующее: если значение больше нуля, то оно уменьшается, если же значение равно нулю, поток приостанавливается до того момента, когда значение семафора станет положительным, тогда значение уменьшается и поток продолжает работу. Увеличение значения семафора, возможно всегда, эта операция не предполагает блокировки. Однако значение семафора не должно выходить за границы типа unsigned int.

Рассмотрим функции для работы с семафорами (заголовочный файл–semaphore.h).

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

Функция инициализирует семафор sem и присваивает ему значение value.

Если параметр pshared больше нуля, семафор может быть доступен нескольким процессам, если pshared равен нулю, семафор создается для использования внутри одного процесса. Функция возвращает ноль в случае успеха.

int sem_destroy (sem_t *sem)

Функция разрушает семафор sem и возвращает ноль в случае успеха.

int sem_getvalue (sem_t *sem, int *sval)

Функция записывает значение семафора sem в *sval. Необходимо понимать, что если несколько потоков используют семафор, полученное значение семафора может быть устаревшим.

int sem_post (sem_t *sem)

Функция увеличивает значение семафора sem на единицу.

int sem_wait (sem_t *sem)

Если текущее значение семафора больше нуля, функция уменьшает значение семафора sem на единицу. Если текущее значение семафора равно нулю, выполнение потока, вызвавшего функцию sem_wait, приостанавливается до тех пор, когда значение семафора станет положительным, тогда значение семафора уменьшается на единицу и поток продолжает работу.

int sem_trywait (sem_t *sem)

Если текущее значение семафора больше нуля, функция уменьшает значение семафора sem на единицу и возвращает ноль. Если текущее значение семафора равно нулю, функция возвращает не нулевое значение. Функция sem_trywait не останавливает работу потока.

Обратите внимание!

Для корректной работы описанных семафоров, необходимо при компиляции программы использовать команду:

g++ <исходный файл> -o <исполняемый файл> -lpthread.

Лістинг програми а

#include<stdio.h>

#include<unistd.h>

#include<sys/ipc.h>

#include<sys/shm.h>

#include<sys/sem.h>

#include<sys/wait.h>

#include<string.h>

int semid;

sembuf Plus1 = { 0, 1, 0 };

sembuf Minus1 = { 0, -1, 0 };

void func(int, char[], int[]);

void clear();

void space();

char s[100][2];

int n;

int main()

{

char str[] = "";

static int mas[100];

semid = semget(IPC_PRIVATE, 1, IPC_CREAT|0666) ;

if (semid < 0)

{

printf("Error\n");

return 0;

}

printf("Enter string: ");

scanf("%s", str);

printf("Enter N:");

scanf("%d", &n);

int i;

printf("Enter symbols:\n");

for (i = 0; i < n; i++)

{

clear();

scanf("%c", &s[i][0]);

space();

scanf("%c", &s[i][1]);

}

semop(semid, &Plus1, 1);

for (i = 0; i < 4; i++)

{

if (fork() == 0)

{

func(i, str, mas);

return 1;

}

}

for (i = 0; i < 4; i++)

{

wait(NULL);

}

printf("Result:\n");

printf("%s\n", str);

return 1;

}

void func(int part, char str[], int mas[])

{

semop(semid, &Minus1, 1);

int tmpLen = strlen(str) / 4;

int start = part * tmpLen;

int end = start + tmpLen;

if (part == 3)

{

end = strlen(str);

}

int i, j;

for(i = start; i < end; i++)

{

for (j = 0; j < n; j++)

{

if ((str[i] == s[j][0]) && (mas[i] == 0))

{

str[i] = s[j][1];

mas[i] = 1;

}

}

}

semop(semid, &Plus1, 1);

}

void clear()

{

while(getchar() != '\n');

}

void space()

{

while(getchar() != ' ');

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]