使用C

时间:2015-05-23 14:51:46

标签: c linux multithreading mutex

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

这就是我遇到问题的地方。我正在考虑使用表来存储结果,但老师告诉我,这不是正确的解决方案,因为那时我不必使用互斥锁。任何想法做什么以及如何同步它?我对pthread和互斥体完全不熟悉。

这是我到现在为止所得到的。我还在努力,所以它目前还没有工作,它只是一个程序的计划,我想添加互斥锁。我希望这不是全部错。 ; 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;
}

编辑:如果不清楚 - 我需要帮助解决方案如何将所有线程的结果存储在公共变量中并同步它。

EDIT2:可能的解决方案 - 所有线程共享的全局变量result。返回主线程,它会被添加到一些局部变量中,所以我可以用另一个线程的结果覆盖它的值。当然它需要一些同步,所以在我在主线程中添加它之前,另一个线程不会覆盖它。你觉得怎么样?

EDIT3:我已经用我现在拥有的代码更新了代码。输出给了我8-9个术语的值(术语printf),然后程序仍在工作,什么都没有显示。评论的printf告诉我,虽然循环是无限的。局部变量fi​​nal也只是结果的最后一个值。我做错了什么?

4 个答案:

答案 0 :(得分:1)

主要线程应该是添加术语的主线程,但个别线程必须将结果写入同一个变量。我通常希望每个线程将自己的术语添加到结果中(这确实需要互斥锁),或者可能将其结果放入数组(如您所建议的),或者将其添加到共享队列(这需要互斥锁) ,甚至将其写入管道。不过,它可以通过老师的方式完成。

要解决的一个关键问题是,您需要进行明确不同的操作才能进行同步:

  • 各种计算线程&#39;写入共享结果变量
  • 主线程读取结果变量

您不能仅使用单个同步构造,因为您无法区分计算线程和主线程。解决这个问题的一种方法是同步计算线程&#39;根据需要通过互斥锁写入,并同步那些 vs 。主线程通过信号量或条件变量读取。您也可以使用一个或多个其他互斥锁,但不能干净利落。

附加说明:

  • 您的线程存放其术语的结果变量必须是全局的。线程无权访问启动它们的函数的局部变量。
  • 您的term()函数的签名对于线程启动函数不正确。参数必须是void *类型。
  • 线程启动函数与其他函数没有区别,因为它们的局部变量只能在函数执行期间访问。特别是,返回一个指向局部变量的指针不能做任何有用的事情,因为以后取消引用这样一个指针的任何尝试都会产生未定义的行为。

我不打算为你写作业,但这是一种可行的方法:

  1. 主线程初始化互斥锁和两个信号量,后者的初始值为零。
  2. 主线程启动所有计算线程。虽然它很难看,你可以通过将它们转换为void *,然后将它们放回term()函数中来提供它们的数字参数(因为它的参数应该是void *} )。
  3. 然后主线程循环。在每次迭代中,它
    1. 等待信号量1(sem_wait()
    2. 将全局result变量的值添加到正在运行的总计
    3. 发布信号量2(sem_post()
    4. 如果执行了多次迭代,就像有线程一样,从循环中断,
  4. 同时,每个计算线程都这样做:

    1. 计算相应字词的值
    2. 锁定互斥锁
    3. 将术语值存储在全局result变量
    4. 发布信号量1
    5. 等待信号量2
    6. 解锁互斥锁
    7. <强>更新

      要为此作业使用条件变量,必须确定哪些共享状态受这些条件变量的保护,因为必须始终防止在条件变量上等待等待。

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

      1. 准备从计算线程接收值,
      2. 准备主线程阅读。
      3. 计算线程需要等待第一个状态,主线程需要等待(重复)第二个状态。由于线程需要等待两种不同的条件,因此需要两个条件变量。这是使用这些想法的另一种方法:

        1. 主线程初始化互斥锁和两个条件变量,并将result设置为-1
        2. 主线程启动所有计算线程。虽然它很难看,你可以通过将它们转换为void *,然后将它们放回term()函数中来提供它们的数字参数(因为它的参数应该是void *} )。
        3. 主线程锁定互斥锁
        4. 然后主线程循环。在每次迭代中,它
          1. 测试result是否为非负数。如果是这样的话
            1. result变量的值添加到正在运行的总计
            2. 如果有多个术语被添加,因为有线程,从循环中断
            3. result设置为-1
            4. 信号条件变量1
          2. 等待条件变量2
        5. 从循环中断开后,主线程解锁互斥锁
        6. 同时,每个计算线程都这样做:

          1. 计算其术语
          2. 锁定互斥锁
          3. 循环:
            1. 检查result的值。如果它小于零则从循环中断开
            2. 等待条件变量1
          4. 从循环中断开后,将result设置为计算的术语
          5. 信号条件变量2
          6. 解锁互斥锁

答案 1 :(得分:0)

<?php $a="cat"; $html=<<<HTML <html> <script> var b ="$a"; document.write(b); </script> </html> HTML; echo $html;?> 在所有主题之间共享,因此您需要使用互斥锁(可能是您的老师希望看到的内容)保护它(

number

您还应该删除DETACHED状态并在打印结果之前在主程序结束时执行线程连接

答案 2 :(得分: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;
}

此代码创建一个全局互斥pthread_mutex_t lock(在这种情况下)确保任何人不会同时执行相同的代码:基本上当一个线程执行pthread_mutex_lock(&lock)时,它禁止任何其他thread执行该部分代码,直到“原始”线程执行pthread_mutex_unlock(&lock)

另一个重要的部分是pthread_join:它的作用是强制主线程等待执行所创建的每个其他线程;这样,float result[10]是在主线程中实际处理之前编写的(在本例中是最后一条打印指令)。

除此之外,我修复了其他用户指出的代码中的一些错误。

答案 3 :(得分:0)

如果结果是单个变量,那么一种解决方案是使用20个互斥量的数组:aMutex [20] ;.主锁定所有20个互斥锁然后启动pthreads。每个pthread [i]计算一个本地术语,等待aMutex [i],将其值存储到结果中,然后解锁aMutex [10 + i]。在main()for(i = 0; i&lt; 20; i ++){unlock aMutex [i]允许pthread [i]将其值存储到result中,然后等待aMutex [10 + i]知道结果是更新,然后将结果添加到总和。 }