main L4 Created by Никита Волобуев on 22 04 15 Copyright 2015 Никита В

  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
125
126
127
128
129
130
//
// main.c
// L4
//
// Created by Никита Волобуев on 22.04.15.
// Copyright (c) 2015 Никита Волобуев. All rights reserved.
//
#include <pthread.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.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) для удаления семафора и высвобождения его ресурсов. */