如何避免在线程中使用全局变量

时间:2012-10-08 06:32:06

标签: c global-variables

我编写了一个C程序,它使用两个线程进行读写。我已经将两个线程都访问的变量声明为Global。在这种情况下如何避免使用全局变量。

6 个答案:

答案 0 :(得分:4)

请查看C中pthread库的以下方法,以便在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);

类似地,您可以查看信号量以同步C线程中全局变量的使用。

答案 1 :(得分:3)

您真的需要共享变量,还是每个线程实际上需要2个相同数据的副本?如果是这样,不是将其声明为全局,而是在创建时将其作为参数传递给线程。

如果确实需要共享,则需要使用互斥锁进行保护。如果将共享变量与互斥锁一起捆绑到结构中,并在创建时将其作为参数传递给线程,您仍然可以取消全局变量。

答案 2 :(得分:3)

  

请避免在这种情况下使用全局变量。

无需避免全局变量。只有你必须考虑的是一些锁定机制的有效数据。

将所有全局变量放入结构中是为了在项目增长时提供可读性和代码控制。

我建议你使用互斥锁..这是一个修改过的示例代码。

#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);
}   

答案 3 :(得分:2)

我认为你问的是如何通过在启动期间传递他们的工作数据来避免让你的线程访问全局变量。

请参阅pthread_create的最后一个参数,它允许您定义一个用户定义的自定义指针,它可以是您想要的任何内容。使用它来传递数据(例如结构地址甚至是按值,只要该值可以适合平台的void指针大小。

例如,父母可以通过这样做发送子线程数据:

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

子proc将通过以下方式引用它:

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

我希望这是有道理的,希望它能帮助你理解如何将数据传递给线程proc,这就是我认为你的问题。

答案 4 :(得分:1)

  1. 如果您希望每个线程都有一个单独的变量副本,请将变量声明为线程本地。

答案 5 :(得分:1)

你可以制作结构。我通常使用一个名为globalArgs的结构,其中我将所有全局变量放在那里。

这样的事情:

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

或者,您可以将所有值作为参数传递给需要的函数。