2

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

4

6 回答 6

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

同样,您可以查看 Semaphores 以同步 C 线程中全局变量的使用。

于 2012-10-08T06:46:12.567 回答
3

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

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

于 2012-10-08T06:46:32.787 回答
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);
}   
于 2012-10-08T06:46:58.043 回答
2

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

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

例如,父母可以通过以下方式发送子线程数据:

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

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

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

我希望这是有道理的,并希望它可以帮助您了解如何将数据传递给线程 proc,这就是我认为您的问题所在。

于 2012-10-08T06:50:18.603 回答
1
  1. 如果您希望每个线程都有一个单独的变量副本,请将变量声明为线程本地的。
于 2012-10-08T06:37:28.183 回答
1

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

像这样的东西:

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

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

于 2012-10-08T06:40:11.160 回答