So below is a program written so as to mimic a basic webpage counter. 'cnt' holds the counter value and the program is repeated 100 times to mimic 100 visits to the page.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
// repeat 100 times to mimic 100 random visits to the page
#define RPT 100
//web page visit counter
int cnt=0;
void* counter() {
int cntLocalCopy;
float r;
cntLocalCopy = cnt;
// mimicking the work of the sever in serving the page to
// the browser
r = rand() % 2000;
usleep(r);
cnt = cntLocalCopy + 1;
}
int main () {
int i;
float r;
pthread_t tid[RPT];
// seed the random number sequence
srand(time(NULL));
for (i=0; i<RPT; i++) {
// mimicking the random access to the web page
r = rand() % 2000;
usleep(r);
// a thread to respond to a connection request
pthread_create (&tid[i], NULL, &counter, NULL);
}
// Wait till threads complete.
for (i=0; i<RPT; i++) {
pthread_join(tid[i], NULL);}
// print out the counter value and the number of mimicked visits
// the 2 values should be the same if the program is written
// properly
printf ("cnt=%d, repeat=%d\n", cnt, RPT);
}
So the code produced some output as per below (with 'cnt' being the number of visitors to 'the website' and repeat being '100 random visits to the site'.
This is a Systems Engineering and multithreaded problem.
Basically I would like to know why the output is roughly 60 and not 100 (or approximetly) and also how I could go about making the changes to make the code run more accurately and conistently than the value sthat I am getting.
cnt=63, repeat=100
cnt=59, repeat=100
cnt=58, repeat=100
cnt=63, repeat=100
cnt=59, repeat=100
cnt=59, repeat=100
You get smaller values due to data races: two threads may read the same value of cnt
and both update it to cnt+1
instead of ctn+1
and cnt+2
:
Thread 1 | Thread 2 | Comment
-----------------------+-------------------------+--------------------
cntLocalCopy = cnt; | | cntLocalCopy <- 0
usleep(r); |
| cntLocalCopy = cnt; | cntLocalCopy <- 0
| usleep(r);
cnt = cntLocalCopy + 1;| | cnt <- 1
| cnt = cntLocalCopy + 1; | cnt <- 1
You need to take action against those data race, with semaphores, mutex, memory barriers, atomic functions, etc.