The following program creates a number of threads running concurrently. All of them share the same global counter variable. They lock the counter and update and display the value of the counter. The lock mechanism is done by a semaphore. This shows the first use of semaphores: a lock!
Click here to download a copy of this program.
#include <stdio.h> #include <stdlib.h> #include <thread.h> #include <synch.h> #define NO_THREADS 5 /* current, no more than 5 */ sema_t Lock; /* the protecting semaphore */ int Counter, Max_Run; /* the shared counter */ void *Counting(void *voidPTR) { int *intPTR = (int *) voidPTR; int Name = *intPTR; char filler[20]; int i; for (i = 0; i < Name*2; i++) filler[i] = ' '; filler[i] = '\0'; printf("%sThread %d started\n", filler, Name); for (i = 0; i < Max_Run; i++) { thr_yield(); /* rest for unspecified time*/ sema_wait(&Lock); /* enter critical section */ Counter++; /* do updating and printing */ printf("%sThread %d reports: new counter value = %d\n", filler, Name, Counter); sema_post(&Lock); /* leaving critical section */ } printf("%sThread %d ends\n", filler, Name); thr_exit(0); } void main(int argc, char *argv[]) { thread_t ID[NO_THREADS]; /* thread IDs */ size_t Status[NO_THREADS]; /* thread status */ int Argument[NO_THREADS]; /* thread argument */ int i; if (argc != 2) { printf("Use %s #-of-iterations\n", argv[0]); exit(0); } Max_Run = abs(atoi(argv[1])); printf("Parent started ...\n"); Counter = 0; sema_init(&Lock, 1, USYNC_THREAD, (void *) NULL); /* init sem. */ printf("Parent is about to create %d threads\n", NO_THREADS); for (i = 0; i < NO_THREADS; i++) { /* create all threads */ Argument[i] = i; thr_create(NULL, 0, Counting, (void *) &(Argument[i]), 0, (void *) &(ID[i])); } for (i = 0; i < NO_THREADS; i++) { /* wait for all threads */ thr_join(ID[i], 0, (void *) &(Status[i])); printf("Parent found thread %d done\n", i); } printf("Parent exits ...\n"); }