使用多线程时保护全局变量

Protecting global variable when using multiple threads

我在 linux 中编写的 C 程序创建了多个线程(在本例中为 8 个),每个线程应该 运行 函数 compute() 将增加一个全局变量 "total" 增加 1000。该程序目前在这方面按预期工作,因为它输出的最终总数为 8000。

目前,线程执行计算函数和更改 "total" 变量的顺序无关紧要,但我想确保每个线程在不使用全局变量之前不会更改它通过任何其他线程。

如果有人能指出我应该如何实施 POSIX 信号量以实现此目标的正确方向,我将不胜感激,因为这 area/threads 通常对我来说是新的。

程序的当前代码如下。 非常感谢!

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <semaphore.h>

#define N 8 /* define the total number of processes we want */
/* Set global variable */
float total=0;

/* compute function just does something. */
int compute()
{
  int i;
  float oldTotal =0, result =0;

  /*for a large number of times just square root and square the arbitrary number 1000*/
  for (int i = 0; i < 2000000000; i++)  //Arbitrary number to allow process to run for a while.
      {
        result = sqrt(1000.0)*sqrt(1000.0);
      }

  /*Print the result - should be no suprise*/
  printf("Result is %f\n", result); 

  /*We want to keep a running total in the global variable total*/
  oldTotal = total;   
  total = oldTotal + result;

  /*Print the running total so far*/
  printf("Total is %f\n", total);
  return(0);
}


void* thread_procedure(void* param)
{

    int i = (int)param;
    /* give a message about the proc ID */
    printf("Process Id for process %d is %d\n",i,getpid());
    /* call the function to do some computation. If we used sleep
    The process would simply sleep. We do not want that */

    compute(); 

    return NULL;
}


int main()
{
  int i, j;
  sem_init(&mutex, 0, 1); //Initialise mutex 
  pthread_t thread[N];   //Array of threads, N number of processes     


  printf("\n"); /* bit of whitespace */
  /* We want to loop to create the required number of processes
  Note carefully how only the child process is left to run */
  for(i=0;i<N;i++)
    {
      /* start new thread and catch it if it/one fails */
      j = pthread_create(&thread[i], NULL, &thread_procedure, (void*)i);
      if (j)
          {
            printf("Error");
            exit(1);
          }
    }


  /* joining with threads */
  for(i=0;i<N;i++)
       {
          pthread_join(thread[i], NULL);
       }

  sem_destroy(&mutex); 
  /* nothing else to do so end main function (and program) */
  return 0;
} // end function: main

听起来你需要使用互斥量或信号量

如果我可以建议使用 pthread mutex 也可以实现对共享变量的互斥,下面的示例可以实现。它可能会更快地完成您想要完成的事情。

#include <pthread.h>

//Shared global variable
float total = 0;

//Shared lock
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 

//some thread function that adds 1,000 to total one thread at a time
void *compute(){

    //If no thread is using the lock, acquire lock and add 1,000 to total. The lock prevents other threads from executing this piece of code during a context switch. 
    pthread_mutex_lock(&lock);
    total += 1000;
    //Release lock
    pthread_mutex_unlock(&lock);

    return NULL;

}

这样,如果线程T1执行了计算函数并且锁是空闲的,它会获取锁,增加total,然后释放锁。如果线程 T2T1 拥有锁时调用计算,T2 将无法继续执行代码中超出该点的操作,并且将等到锁资源被 [=11= 释放].因此它保护了全局变量;当一个线程持有锁时,希望改变共享变量的线程无法同时这样做。