Search code examples
cmultithreadingconcurrencyoperating-systemsystem

Webpage counter where the counter value is smaller than the number of visits


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

Solution

  • 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+1and 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.