#include <stdlib.h> 
#include <stdio.h> 
#include <errno.h> 
#include <pthread.h> 
#include <semaphore.h> 

sem_t sem, sem_B, sem_C, sem_C2; 

int result; 

pthread_t thread_A, thread_B, thread_C, thread_D, thread_E; 

void * thread_func_C(void *arg) 
{ 
float sum, i; 
sem_post(&sem_C); 
printf ("Поток C начат\n"); 
for (i=1;i<1000000000;i*=2) 
sum+=1/i; 
printf ("Рассчет потоком C завершен = %.3f \n",sum); 
sem_wait(&sem_C2); 
printf ("Поток C завершен\n"); 
} 

void * thread_func_D(void *arg) 
{ 
printf ("Поток D начат\n"); 
float sum=0, i; 
for (i=1;i<1000000;i++) 
sum+=1/i; 
printf ("Рассчет потоком D завершен = %.3f \n",sum); 
sem_wait (&sem); 
printf ("Поток D завершен\n"); 
} 

void * thread_func_E(void *arg) 
{ 
printf ("Поток E начат\n"); 
float sum=0, i; 
for (i=1;i<1000000;i++) 
sum+=1/(i*2); 
printf ("Рассчет потоком E завершен = %.3f \n",sum); 
printf ("Поток E завершен\n"); 
sem_post(&sem); 
} 

void * thread_func_A(void *arg) 
{ float sum=1, i; 
printf("Поток А начат\n"); 
sem_wait(&sem_B); 
for (i=1;i<33;i++) 
{ 
sum*=i; 
if (i==5) { 
result = pthread_create(&thread_C, NULL, thread_func_C, NULL); 
if (result != 0) { 
perror("Ошибка в создании потока C"); 
return EXIT_FAILURE; 
} 
} 
} 
printf("Поток А рассчитал 32! = %.0f\n",sum); 
printf("Поток A завершен\n"); 
} 

void * thread_func_B(void *arg) 
{ 
float sum=1,i; 
printf("Поток B начат\n"); 
sem_post(&sem_B); 
sem_wait(&sem_C); 
for (i=1;i<5000000;i++) 
{ 
if (i==1000000) { 
result = pthread_create(&thread_D, NULL, thread_func_D, NULL); 
if (result != 0) { 
perror("Ошибка в создании потока D"); 
return EXIT_FAILURE; 
} 
} 
if (sum>0||sum==0) {sum-=i;continue;} 
if (sum<0) {sum+=i;continue;} 
} 
printf ("Рассчет потоком B завершен = %.0f \n",sum); 
printf ("Поток B завершен\n"); 
sem_post(&sem_C2); 
} 

int main(int argc, char * argv[]) 
{ 
printf ("\033[0d\033[2J"); 

sem_init(&sem, 0, 0 ); 
sem_init(&sem_B,0,0 ); 
sem_init(&sem_C,0,0 ); 
sem_init(&sem_C2,0,0); 

result = pthread_create(&thread_A, NULL, thread_func_A,NULL); 
if (result != 0) { 
perror("Ошибка в создании потока А"); 
return EXIT_FAILURE; 
} 

result = pthread_create(&thread_B, NULL, thread_func_B, NULL); 
if (result != 0) { 
perror("CОшибка в создании потока В"); 
return EXIT_FAILURE; 
} 

result = pthread_join(thread_A, NULL); 
if (result != 0) { 
perror("Невозможно проверить поток А"); 
return EXIT_FAILURE; 
} 

result = pthread_join(thread_B, NULL); 
if (result != 0) { 
perror("Невозможно проверить поток В"); 
return EXIT_FAILURE; 
} 

pthread_create(&thread_E, NULL, thread_func_E, NULL); 
pthread_join(thread_D, NULL); 
result = pthread_join(thread_E, NULL); 
if (result != 0) { 
perror("Невозможно проверить поток Е"); 
return EXIT_FAILURE; 
} 
sem_destroy (&sem); 
sem_destroy (&sem_B); 
sem_destroy (&sem_C); 
sem_destroy (&sem_C2); 

printf("Готово\n"); 
return EXIT_SUCCESS; 
} 


//запуск программы: gcc -o ExeFile the -prog.c -lp thread
                           имя файла результ.