JMU
Shared Variables in Pthreads
An Introduction


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


Review
Implications for Variable Sharing
Using Function/Block Scope Appropriately
Using Function/Block Scope Appropriately (cont.)
unixexamples/pthreads/memory0.c
        #include <pthread.h>
#include <stdio.h>    // For printf()
#include <stdlib.h>   // For exit()
#include <string.h>   // For strlen()
#include <unistd.h>   // For sleep() if needed


static void
*code_for_thread1(void *arg)
{
  int count;
  
  printf("count in thread 1 is initially %d\n", count);
  count = 20;
  printf("count in thread 1 is finally   %d\n", count);
  return NULL;
}



int
main(void)
{
  int       count;
  pthread_t thread1;
  void      *thread1_result;

  count = 100;
  printf("count in main thread is initially %d\n", count);

  pthread_create(&thread1, NULL, code_for_thread1, NULL);
  pthread_join(thread1, &thread1_result);
  
  printf("count in main thread is finally   %d\n", count);
  exit(0);
}
        
Using Global Segments Appropriately
Using Global Segments Appropriately (cont.)
unixexamples/pthreads/memory1.c
        #include <pthread.h>
#include <stdio.h>    // For printf()
#include <stdlib.h>   // For exit()
#include <string.h>   // For strlen()
#include <unistd.h>   // For sleep() if needed


int count;


static void
*code_for_thread1(void *arg)
{
  printf("count in thread 1 is initially %d\n", count);
  count = 20;
  printf("count in thread 1 is finally   %d\n", count);
  return NULL;
}



int
main(void)
{
  pthread_t thread1;
  void      *thread1_result;

  count = 10;
  printf("count in main thread is initially %d\n", count);

  pthread_create(&thread1, NULL, code_for_thread1, NULL);
  pthread_join(thread1, &thread1_result);
  
  printf("count in main thread is finally   %d\n", count);
  exit(0);
}
        
An Incorrect Use of the Stack
An Incorrect Use of the Stack (cont.)
unixexamples/pthreads/memory4.c
        #include <pthread.h>
#include <stdio.h>    // For printf()
#include <stdlib.h>   // For exit()
#include <string.h>   // For strlen()
#include <unistd.h>   // For sleep() if needed


int *ptr;


static void
useless_count(void)
{
  int count = 0;
  ptr = &count;

  count++;
}


static void
*code_for_thread1(void *arg)
{
  printf("count in thread 1 is initially %d\n", *ptr);
  useless_count();
  printf("count in thread 1 is finally   %d\n", *ptr);
  return NULL;
}


int
main(void)
{
  pthread_t thread1;
  void      *thread1_result;

  // What happens if you remove the following statement?
  useless_count();
  printf("count in main thread is initially %d\n", *ptr);

  pthread_create(&thread1, NULL, code_for_thread1, NULL);
  pthread_join(thread1, &thread1_result);
  
  printf("count in main thread is finally   %d\n", *ptr);
  exit(0);
}
        
An Inappropriate Use of a Local Static Variable
An Inappropriate Use of a Local Static Variable (cont.)
unixexamples/pthreads/memory3.c
        #include <pthread.h>
#include <stdio.h>    // For printf()
#include <stdlib.h>   // For exit()
#include <string.h>   // For strlen()
#include <unistd.h>   // For sleep() if needed


int *ptr;


static void
running_count(void)
{
  static int count = 0;
  ptr = &count;

  count++;
}


static void
*code_for_thread1(void *arg)
{
  printf("count in thread 1 is initially %d\n", *ptr);
  running_count();
  printf("count in thread 1 is finally   %d\n", *ptr);
  return NULL;
}


int
main(void)
{
  pthread_t thread1;
  void      *thread1_result;

  running_count();
  printf("count in main thread is initially %d\n", *ptr);

  pthread_create(&thread1, NULL, code_for_thread1, NULL);
  pthread_join(thread1, &thread1_result);
  
  printf("count in main thread is finally   %d\n", *ptr);
  exit(0);
}
        
A Very Inappropriate Use of the Stack
A Very Inappropriate Use of the Stack (cont.)
unixexamples/pthreads/memory2.c
        #include <pthread.h>
#include <stdio.h>    // For printf()
#include <stdlib.h>   // For exit()
#include <string.h>   // For strlen()
#include <unistd.h>   // For sleep() if needed


int *ptr;


static void
*code_for_thread1(void *arg)
{
  printf("count in thread 1 is initially %d\n", *ptr);
  *ptr = 20;
  printf("count in thread 1 is finally   %d\n", *ptr);
  return NULL;
}



int
main(void)
{
  int       count;
  pthread_t thread1;
  void      *thread1_result;

  ptr   = &count;
  count = 10;
  printf("count in main thread is initially %d\n", *ptr);

  pthread_create(&thread1, NULL, code_for_thread1, NULL);
  pthread_join(thread1, &thread1_result);
  
  printf("count in main thread is finally   %d\n", *ptr);
  exit(0);
}
        
A Very, Very Inappropriate Use of the Stack
A Very, Very Inappropriate Use of the Stack (cont.)
unixexamples/pthreads/memory6.c
        #include <pthread.h>
#include <stdio.h>    // For printf()
#include <stdlib.h>   // For exit()
#include <string.h>   // For strlen()
#include <unistd.h>   // For sleep() if needed


int *ptr;

static void
some_function(void)
{
  printf("count in some_function() in thread 1 is initially %d\n", *ptr);
  *ptr = 20;
  printf("count in some_function() in thread 1 is finally   %d\n", *ptr);
}


static void
*code_for_thread1(void *arg)
{
  int     count;
  ptr   = &count;
  count = 10;

  printf("count in thread 1 is initially %d\n", *ptr);
  some_function();
  printf("count in thread 1 is finally   %d\n", *ptr);
  return NULL;
}



int
main(void)
{
  pthread_t thread1;
  void      *thread1_result;

  // What happens if the following is included?
  //printf("count in main thread is initially %d\n", *ptr);

  pthread_create(&thread1, NULL, code_for_thread1, NULL);
  pthread_join(thread1, &thread1_result);
  
  // What happens if the following is included?
  //printf("count in main thread is finally   %d\n", *ptr);
  exit(0);
}
        
Some Important Points
Might Seem Appropriate But Isn't
Might Seem Appropriate But Isn't (cont.)
unixexamples/pthreads/memory5.c
        #include <pthread.h>
#include <stdio.h>    // For printf()
#include <stdlib.h>   // For exit()
#include <string.h>   // For strlen()
#include <unistd.h>   // For sleep() if needed


int *ptr1, *ptr2;



static void
*code_for_thread1(void *arg)
{
  static int n_thread1 = 10;
  ptr1 = &n_thread1;

  printf("n_thread1 in thread 1 %d\n", *ptr1);

  // What happens if the following is included?
  //printf("n_thread2 in thread 1 %d\n", *ptr2);
  return NULL;
}


static void
*code_for_thread2(void *arg)
{
  static int n_thread2 = 20;
  ptr2 = &n_thread2;
  

  printf("n_thread1 in thread 2 %d\n", *ptr1);
  printf("n_thread2 in thread 2 %d\n", *ptr2);
  return NULL;
}


int
main(void)
{
  pthread_t thread1, thread2;
  void      *thread1_result, *thread2_result;

  pthread_create(&thread1, NULL, code_for_thread1, NULL);

  pthread_join(thread1, &thread1_result);

  pthread_create(&thread2, NULL, code_for_thread2, NULL);

  pthread_join(thread2, &thread2_result);

  printf("n_thread1 in main thread after join %d\n", *ptr1);
  printf("n_thread2 in main thread after join %d\n", *ptr2);

  exit(0);
}