Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中使用互斥体同步pthreads_C_Linux_Multithreading_Mutex - Fatal编程技术网

在C中使用互斥体同步pthreads

在C中使用互斥体同步pthreads,c,linux,multithreading,mutex,C,Linux,Multithreading,Mutex,我必须编写一个程序,计算公式(x^I)/I!给出的前10个术语的系列(对不起,我的语言,这是我第一次用英语谈论数学)!。所以,基本上它是微不足道的。但是,有一些特殊的要求。每一项都要用独立的线程来计算,每个线程都是并行工作的。然后,他们都将结果保存到名为result的公共变量中。之后,它们必须由主线程添加,主线程将显示最终结果。所有这些都使用pthread和mutex 这就是我的问题所在。我曾考虑使用表来存储结果,但老师告诉我,这不是正确的解决方案,因为这样我就不必使用互斥体。你知道怎么做以及如

我必须编写一个程序,计算公式(x^I)/I!给出的前10个术语的系列(对不起,我的语言,这是我第一次用英语谈论数学)!。所以,基本上它是微不足道的。但是,有一些特殊的要求。每一项都要用独立的线程来计算,每个线程都是并行工作的。然后,他们都将结果保存到名为result的公共变量中。之后,它们必须由主线程添加,主线程将显示最终结果。所有这些都使用pthread和mutex

这就是我的问题所在。我曾考虑使用表来存储结果,但老师告诉我,这不是正确的解决方案,因为这样我就不必使用互斥体。你知道怎么做以及如何同步吗?我对pthread和mutex一无所知

这是我到现在为止得到的。我还在研究它,所以它现在不起作用,它只是一个程序的方案,我想在其中添加互斥。我希望这不全是错的;p

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

int number = 0;
float result = 0;
pthread_mutex_t term_lock;
pthread_mutex_t main_lock;
int save = 0; //condition variable

int factorial(int x) { 
        if(x==0 || x==1)
                return 1;

        return factorial(x-1)*x;
}

void  *term(void *value) {  
        int x = *(int *)value;
        float w;
        if(save == 0) {
            pthread_mutex_lock(&term_lock);
            w = pow(x, number)/factorial(number);
            result = w;
            printf("%d term of series with x: %d  is: %f\n", number, x, w);
            number++;
            save = 1;
            pthread_mutex_unlock(&term_lock);
        }
        return NULL;
}

int main(void) {

        int x, i, err = 0;
        float final = 0;
        pthread_t threads[10];

        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

        printf("Get X: \n");
        scanf("%d", &x);
        for(i=0; i<10; i++)
        {
                err = pthread_create(&threads[i], &attr, (void *)term, &x);
                if(err) {
                        printf("Error creating threads.\n");
                        exit(-1);
                }
        }
        i = 0;
        while (number <= 10) {
            //printf("While Result: %f, final %f\n", result, final); - shows that it's infinite loop
            if(save) {
                pthread_mutex_lock(&main_lock); 
                final = final + result;
                save = 0;
                pthread_mutex_unlock(&main_lock);   
                printf("If Result: %f, final %f\n", result, final); //final == last result
            }
        }
        return 0;
}
#包括
#包括
#包括
#包括
整数=0;
浮动结果=0;
pthread_mutex_t term_lock;
pthread_mutex_t main_lock;
int save=0//条件变量
因式阶乘(因式x){
如果(x==0 | | x==1)
返回1;
收益阶乘(x-1)*x;
}
无效*项(无效*值){
int x=*(int*)值;
浮动w;
如果(保存==0){
pthread_mutex_lock(&term_lock);
w=功率(x,数)/阶乘(数);
结果=w;
printf(“%d个x:%d的系列项为:%f\n”,编号为x,w);
数字++;
save=1;
pthread_mutex_unlock(&term_lock);
}
返回NULL;
}
内部主(空){
int x,i,err=0;
最终浮点数=0;
pthread_t线程[10];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread\u attr\u setdetachstate(&attr,pthread\u CREATE\u distached);
printf(“获取X:\n”);
scanf(“%d”和&x);

对于(i=0;i所有线程之间共享
编号
,因此您需要使用互斥锁来保护该编号(这可能是您的老师希望看到的)


您还应该删除分离状态,并在打印结果之前在主程序的末尾执行线程连接。主线程应该是添加术语的线程,这是一种相当人为的做法,但是各个线程必须将其结果写入同一个变量。我通常希望每个线程都添加自己的ter将结果(需要互斥),或者可能将其结果放入数组(如您所建议的),或者将其添加到共享队列(需要互斥),甚至将其写入管道

要解决的一个关键问题是,必须对需要同步的不同操作执行以下操作:

  • 各种计算线程对共享结果变量的写入
  • 主线程对结果变量的读取
您不能只使用一个同步构造,因为您无法以这种方式区分计算线程和主线程。一种方法是根据需要通过互斥来同步计算线程的写入,并通过信号量或条件变量来同步这些写入与主线程的读取你也可以用一个或多个额外的互斥体来实现,但不是干净的

补充说明:

  • 线程存放其术语的结果变量必须是全局变量。线程无权访问从中启动它们的函数的局部变量
  • 线程启动函数的
    term()
    函数签名不正确。参数的类型必须为
    void*
  • 线程启动函数与其他函数没有什么不同,因为它们的局部变量只能在函数执行期间访问。特别是,返回指向局部变量的指针不能做任何有用的事情,因为以后尝试取消引用此类指针会产生未定义的行为
我不打算为你写作业,但这里有一个可行的方法:

  • 主线程初始化一个互斥锁和两个信号量,后者的初始值为零
  • 主线程启动所有计算线程。虽然它很难看,但您可以通过将它们转换为
    void*
    ,然后将它们转换回
    term()
    函数(因为它的参数应该是
    void*
    )来为它们提供数值参数
  • 然后主线程循环。在每次迭代中,它
  • 等待信号量1(
    sem\u wait()
  • 将全局
    结果
    变量的值添加到运行总计中
  • 发送到信号量2(
    sem\u post()
  • 如果执行的迭代次数与线程数相同,则会中断循环
  • 同时,每个计算线程执行以下操作:

  • 计算相应项的值
  • 锁定互斥锁
  • 将术语值存储在全局
    结果
    变量中
  • 发送到信号量1
  • 等待信号量2
  • 解锁互斥锁
  • 更新:

    要将条件变量用于此作业,必须确定哪些共享状态受这些条件变量的保护,因为必须始终防止因等待条件变量而被错误唤醒

    在这种情况下,讨论中的共享状态将涉及全局
    result
    变量,计算线程在该变量中返回其结果,这似乎很自然。该变量实际上有两种通用的、相互排斥的状态:

  • 准备好从计算线程接收值,并且
  • 准备好让主线程读取
  • 计算的
    pthread_mutex_t number_mutex;
    pthread_mutex_t result_mutex;
    int number = 0;
    int result = 0;
    
    void  *term(int x) {
      float w;
    
      // Critical zone, make sure only one thread updates `number`
      pthread_mutex_lock(&number_mutex); 
      int mynumber = number++;
      pthread_mutex_unlock(&number_mutex);
      // end of critical zone 
    
      w = pow(x, mynumber)/factorial(mynumber);
      printf("%d term of series with x: %d  is: %f\n", mynumber, x, w);
    
      // Critical zone, make sure only one thread updates `result`
      pthread_mutex_lock(&result_mutex); 
      result += w;
      pthread_mutex_unlock(&result_mutex);
      // end of critical zone 
    
      return (void *)0;
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <pthread.h>
    
    int number=0;
    float result[10];
    pthread_mutex_t lock;
    
    int factorial(int x) {
    
    
        if(x==0 || x==1)
                    return 1;
    
            return factorial(x-1)*x;
    }
    
    void  *term(void *value) {
            int x = *(int *)value;
            float w;
            pthread_mutex_lock(&lock);
            w = pow(x, number)/factorial(number);
            printf("%d term of series with x: %d  is: %f\n", number, x, w);
            result[number] = w;
            number++;
            pthread_mutex_unlock(&lock);
            return NULL;
    }
    
    int main(void) {
    
            int x, i, err;
            pthread_t threads[10];
    
            printf("Get X: \n"); 
            scanf("%d", &x);
    
            for(i=0; i<=9; i++)
            {
                    err = pthread_create(&threads[i], NULL, term, &x);
                    if(err) {
                            printf("Error creating threads.\n");
                            exit(-1);
                    }
            }
    
            for(i = 0; i < 10; i++)
            {
                    pthread_join(threads[i], NULL);
            }
    
            i = 0;
    
            for(i=0; i<=9; i++)
            {
                    printf("%f\n", result[i]);
            }
            return 0;
    }