How to avoid usage of Global variables in threads

2019-07-15 23:55发布

I have written a C program that uses two threads for reading and writing. I have declared the variable which are accessed by both the threads as Global. How to avoid the use of global variables in this case.

6条回答
趁早两清
2楼-- · 2019-07-16 00:13

You can make structs. I usually to use a struct called globalArgs where I put all there global variables.

Something like this:

static typedef struct {
int foo;
int baa;
} globalargs;

Or, you can pass all values as parameters to functions that needs of.

查看更多
Anthone
3楼-- · 2019-07-16 00:23

Please look into following methods of pthread library in C for having exclusive access of Shared Global variables in C:

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);

Similarly, you can look into Semaphores for synchronizing the use of global variables in C threads.

查看更多
啃猪蹄的小仙女
4楼-- · 2019-07-16 00:23

I think you're asking how to avoid having your threads accessing globals by passing them their work-data during startup.

Please see the last parameter to pthread_create, which allows you to define a user-defined custom pointer that can be anything you want. Use that to pass data (such as a struct address or even by-value so long as the value can fit in the platform's size of a void pointer.

For example, a parent can send a child thread data by doing such:

Data data;
pthread_create(&thrd, NULL, threadProc, &data);

The child proc would reference this by:

void *threadProc(void *pv)
{
   Data *pData = (Data*)pv;
   .. use data here...
   pthread_exit(NULL);
}

I hope this makes sense, and hope it helps you understand how to pass data to a thread proc, which was what I think your question is.

查看更多
做自己的国王
5楼-- · 2019-07-16 00:29

Do you truly need a shared variable, or do you actually need 2 copies of the same data for each thread? If so, instead of declaring it global, pass it as an argument to the thread at creation.

If it truly needs to be shared, it will need to be protected by a mutex. You can still also do away with the global variable if you bundle the shared variable into a struct along with the mutex and pass it along to the threads as an argument at creation.

查看更多
爷、活的狠高调
6楼-- · 2019-07-16 00:35
  1. If you want each thread to have a separate copy of the variable, declare the variables as thread local.
查看更多
Evening l夕情丶
7楼-- · 2019-07-16 00:36

HOw to avoid the use of global variables in this case.

There is no need to avoid global variables. Only thing you have to consider is valid data by some lock mechanism.

Putting all global variables in to a struct is for readability and code control when your project grows.

I suggest you to use mutex lock.. Here is an modified sample code.

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


typedef struct 
 {
   double      *a;
   double      *b;
   double     sum; 
   int     veclen; 
 } DOTDATA;

/* Define globally accessible variables and a mutex */

#define NUMTHRDS 4
#define VECLEN 100
   DOTDATA dotstr; 
   pthread_t callThd[NUMTHRDS];
   pthread_mutex_t mutexsum;


void *dotprod(void *arg)
{

   /* Define and use local variables for convenience */

   int i, start, end, len ;
   long offset;
   double mysum, *x, *y;
   offset = (long)arg;

   len = dotstr.veclen;
   start = offset*len;
   end   = start + len;
   x = dotstr.a;
   y = dotstr.b;

   /*
   Perform the dot product and assign result
   to the appropriate variable in the structure. 
   */

   mysum = 0;
   for (i=start; i<end ; i++) 
    {
      mysum += (x[i] * y[i]);
    }

   /*
   Lock a mutex prior to updating the value in the shared
   structure, and unlock it upon updating.
   */
   pthread_mutex_lock (&mutexsum);
   dotstr.sum += mysum;
   pthread_mutex_unlock (&mutexsum);

   pthread_exit((void*) 0);
}

/* 
The main program creates threads which do all the work and then 
print out result upon completion. Before creating the threads,
the input data is created. Since all threads update a shared structure, 
we need a mutex for mutual exclusion. The main thread needs to wait for
all threads to complete, it waits for each one of the threads. We specify
a thread attribute value that allow the main thread to join with the
threads it creates. Note also that we free up handles when they are
no longer needed.
*/

int main (int argc, char *argv[])
{
   long i;
   double *a, *b;
   void *status;      

   /* Assign storage and initialize values */
   a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
   b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));

   for (i=0; i<VECLEN*NUMTHRDS; i++)
    {
     a[i]=1.0;
     b[i]=a[i];
    }

   dotstr.veclen = VECLEN; 
   dotstr.a = a; 
   dotstr.b = b; 
   dotstr.sum=0;

   pthread_mutex_init(&mutexsum, NULL);             

   for(i=0; i<NUMTHRDS; i++)
   {
      /* 
      Each thread works on a different set of data.
      The offset is specified by 'i'. The size of
      the data for each thread is indicated by VECLEN.
      */
      pthread_create(&callThd[i], NULL, dotprod, (void *)i);
   }  

   /* Wait on the other threads */
   for(i=0; i<NUMTHRDS; i++)
   {
      pthread_join(callThd[i], &status);
   }

   /* After joining, print out the results and cleanup */
   printf ("Sum =  %f \n", dotstr.sum);
   free (a);
   free (b);
   pthread_mutex_destroy(&mutexsum);
   pthread_exit(NULL);
}   
查看更多
登录 后发表回答