include pthread include stdio include math include stdlib include sema

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <pthread.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
//#include <dispatch/dispatch.h>
#define M 4 //кол-во писателей
#define N 3 //кол-во читателей
unsigned int iter; //Итерации
sem_t accessM,readresM,orderM; //Семафоры
unsigned int readers = 0; // Число читателей, получающих доступ к ресурсу
void *reader(void *prm)
{
int num1 =*(int*)prm; //Номер читателя
int r;
for(int i;i<iter;i++)
{
if (sem_wait(&orderM)==0)
printf("%d Читатель %d в очереди__________Ч%d\n",i,num1,num1); // Если доступ к библиотеке уже занят, то сообщаем об этом
sem_wait(&readresM); // Ограничиваем доступ для одного читателя
if (readers == 0) // Если на данный момент нет читателей (мы пришли первые)...
sem_wait(&accessM); // ... запрашивает исключительный доступ к библиотеке для читателей
readers++; // +1 читатель
sem_post(&orderM); // Сообщаем на общем уровне, что библиотека занята
sem_post(&readresM); // Даем доступ следующему читателю
printf("%d Работает читатель %d________________Ч%d\n",i,num1,num1); //Читатель работает с библиотекой
r = 1 + rand()%4;
sleep(r);
sem_wait(&readresM); // Ограничиваем доступ для одного читателя
readers--; // -1 читатель
if (readers == 0) // Если больше нет читателей в данный момент
sem_post(&accessM); // ...освобождаем доступ
sem_post(&readresM); // Даем доступ следующему читателю
}
return NULL;
}
void *writer(void *prm)
{
int num2=*(int*)prm; //Номер писателя
int r;
for(int j;j<iter;j++)
{
if(sem_wait(&orderM)==0)
printf("%d Писатель %d в очереди__________П%d\n",j,num2,num2); // Если доступ к библиотеке уже занят, то сообщаем об этом
sem_wait(&accessM); // запрашивает исключительный доступ к библиотеке
sem_post(&orderM); // Сообщаем на общем уровне, что библиотека занята
printf("%d Работает писатель %d________________П%d\n",j,num2,num2); // Писатель работает с библиотекой
r=1+rand()%4;
sleep(r);
sem_post(&accessM); // Освобождаем библиотеку
}
return NULL;
}
int main()
{
pthread_t threadRE[N]; //Дескриптор потока читателей
pthread_t threadWR[M]; //Дескриптор потока писателей
sem_init(&accessM,0,1); /*Инициализируем семафор
(1)указатель на инициализируемый объект-семафор,
(2)флаг, указывающий, должен ли семафор быть разделен с разветвленными процессами,
(3)начальное значение семафора)*/
sem_init(&readresM,0,1);
sem_init(&orderM,0,1);
printf("Введите количество итераций: ");
scanf("%d",&iter);
printf("Iter ОЧЕРЕДЬ/ВЫПОЛНЕНИЕ\n");
int i;
for(i=0;i<M;i++) //Писатели
{
pthread_create(&(threadWR[i]),NULL,writer,(void*)&i); /*Создаем поток
(1)NULL, либо указатель на pthread_t объекта, где функция может хранить поток идентификатор нового потока,
(2)Указатель на структуру pthread_attr_t, которая определяет атрибуты нового потока,
(3)|Процедура, где начинается поток, с arg в качестве единственного аргумента. Если start_routine() возвращает, существует неявный вызов pthread_exit(),
используя значение, возвращаемое start_routine() как статус выхода.|
(4)Аргумент, передаваемый в start_routine.)*/
}
for(i=0;i<N;i++) //Читатели
{
pthread_create(&(threadRE[i]),NULL,reader,(void*)&i);
}
for(i=0;i<N;i++)
{
pthread_join(threadRE[i],NULL); // блокирует работу вызвавшего его потока до завершения thread'а с идентификатором thread
}
for(i=0;i<M;i++)
{
pthread_join(threadWR[i],NULL);
}
sem_destroy(&accessM);
sem_destroy(&readresM);
sem_destroy(&orderM);
}
/*Единственным аргументом функции sem_wait() служит указатель на идентификатор семафора.
Функция sem_wait() приостанавливает выполнение вызвавшего ее потока до тех пор,
пока значение семафора не станет большим нуля, после чего функция уменьшает значение семафора на единицу
и возвращает управление. Функция sem_post() увеличивает значение семафора,
идентификатор которого был передан ей в качестве параметра, на единицу.
Присвоив семафору значение 0, наша программа создает первый поток и вызывает функцию sem_wait().
Эта функция приостановит выполнение функции main() до тех пор, пока функция потока не вызовет функцию sem_post(),
а это случится только после того как функция потока обработает значение переменной id.
Таким образом, мы можем быть уверены, что в момент создания второго потока первый поток уже
закончит работу с переменной id, и мы сможем использовать эту переменную для передачи данных второму потоку.
После завершения обоих потоков мы вызываем функцию sem_destroy(3) для удаления семафора и высвобождения его ресурсов. */