#include #include #include #include #include const int bufSize = 10; int buf[bufSize] ; //буфер int rear = 0 ; //индекс для записи в буфер int front = 0 ; //индекс для чтения из буфера sem_t empty ; //семафор, отображающий насколько буфер пуст sem_t full ; //семафор, отображающий насколько полон буфер pthread_mutex_t mutexD ; //мутекс для операции записи pthread_mutex_t mutexF ; //мутекс для операции чтения unsigned int seed = 101; // инициализатор генератора случайных чисел //стартовая функция потоков – производителей (писателей) void *Producer(void *param) { int pNum = *((int*)param); while (1) { //создать элемент для буфера int data = rand() % 11 - 5 ; //поместить элемент в буфер pthread_mutex_lock(&mutexD) ; //защита операции записи //критическая секция sem_wait(&empty) ; //количество свободных ячеек уменьшить на единицу buf[rear] = data ; rear = (rear+1)%bufSize ; sem_post(&full) ; //количество занятых ячеек увеличилось на единицу ///printf("Producer %d: Writes value = %d to cell [%d] Full = %d\n", pNum, data, rear-1 < 0 ? bufSize-1: rear-1, /// rear > front ? rear-front: bufSize -(front-rear)) ; pthread_mutex_unlock(&mutexD) ; printf("Producer %d: Writes value = %d to cell [%d]\n", pNum, data, rear-1 < 0 ? bufSize-1: rear-1) ; sleep(6); } return nullptr; } //стартовая функция потоков – потребителей (читателей) void *Consumer(void *param) { int cNum = *((int*)param); int result ; while (1) { sleep(10); //извлечь элемент из буфера pthread_mutex_lock(&mutexF) ; //защита операции чтения sem_wait(&full) ; //количество занятых ячеек уменьшить на единицу result = buf[front] ; front = (front+1)%bufSize ; //критическая секция sem_post(&empty) ; //количество свободных ячеек увеличилось на единицу ///printf("Consumer %d: Reads value = %d from cell [%d] Full = %d\n", cNum, result, front-1 < 0 ? bufSize-1: front-1, /// rear >= front ? rear-front: bufSize -(front-rear)) ; pthread_mutex_unlock(&mutexF) ; //обработать полученный элемент printf("Consumer %d: Reads value = %d from cell [%d]\n", cNum, result, front-1 < 0 ? bufSize-1: front-1) ; } return nullptr; } int main() { srand(seed); int i ; //инициализация мутексов и семафоров pthread_mutex_init(&mutexD, nullptr) ; pthread_mutex_init(&mutexF, nullptr) ; sem_init(&empty, 0, bufSize) ; //количество свободных ячеек равно bufSize sem_init(&full, 0, 0) ; //количество занятых ячеек равно 0 //запуск производителей pthread_t threadP[3] ; int producers[3]; for (i=0 ; i<3 ; i++) { producers[i] = i + 1; pthread_create(&threadP[i],nullptr,Producer, (void*)(producers+i)) ; } //запуск потребителей pthread_t threadC[4] ; int consumers[4]; for (i=0 ; i < 4 ; i++) { consumers[i] = i + 1; pthread_create(&threadC[i],nullptr,Consumer, (void*)(consumers+i)) ; } //пусть главный поток тоже будет потребителем int mNum = 0; Consumer((void*)&mNum) ; return 0; }