我写了一个使用两个线程进行读写的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 线程中全局变量的使用。
HOw 以避免在这种情况下使用全局变量。
没有必要避免全局变量。您唯一需要考虑的是某些锁定机制的有效数据。
将所有全局变量放入结构中是为了在项目增长时提高可读性和代码控制。
我建议你使用互斥锁。下面是一个修改后的示例代码。
#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);
}
您真的需要一个共享变量,还是每个线程实际上需要相同数据的 2 个副本?如果是这样,则不要将其声明为全局,而是在创建时将其作为参数传递给线程。
如果确实需要共享,则需要通过互斥锁进行保护。如果将共享变量与互斥锁一起捆绑到结构中,并在创建时将其作为参数传递给线程,则仍然可以取消全局变量。
我想你在问如何通过在启动期间向线程传递工作数据来避免线程访问全局变量。
请参阅要pthread_create的最后一个参数,它允许您定义一个用户定义的自定义指针,该指针可以是您想要的任何内容。使用它来传递数据(例如结构地址甚至按值,只要该值可以适合平台的空指针大小。
例如,父线程可以通过执行以下操作来发送子线程数据:
Data data;
pthread_create(&thrd, NULL, threadProc, &data);
子进程将通过以下方式引用此内容:
void *threadProc(void *pv)
{
Data *pData = (Data*)pv;
.. use data here...
pthread_exit(NULL);
}
我希望这是有道理的,并希望它能帮助您理解如何将数据传递给线程进程,这就是我认为您的问题所在。
- 如果希望每个线程都有单独的变量副本,请将变量声明为线程本地变量。
你可以制作结构。我通常使用一个名为globalArgs
的结构,在那里我把所有的全局变量都放在那里。
像这样:
static typedef struct {
int foo;
int baa;
} globalargs;
或者,您可以将所有值作为参数传递给需要的函数。