c

时间:2016-03-07 18:22:28

标签: c arrays multithreading

我应该有两个线程来搜索数组中的最小元素:第一个搜索前半部分,第二个线程搜索另一半。但是,当我运行我的代码时,它似乎随机选择一个线程。我不确定我做错了什么,但这可能与" mid"部分。我尝试将数组分成两部分,找到中点,然后从那里写出条件,但我可能在某处出错了。我也尝试将数组[i]放在条件中,但在这种情况下只执行thread2。

编辑:我在这里真的很努力,但我没有到达任何地方。我以一种对我有意义的方式编辑了代码,我可能会对#34; min"错了,但现在它甚至没有执行它只是给我一个错误,即使它编译得很好。我只是一个初学者,虽然我确实理解你们所谈论的一切,但我很难实现这些想法,所以真的,任何帮助解决这个问题都是值得赞赏的!

EDIT2:好的,以前的代码完全没有任何意义,我道歉但写作时我已经筋疲力尽了。无论如何,我想出了一些部分有效的东西!我将数组分成两半,但是在使用指针时只能访问第一个元素。但是如果整个阵列被访问它会起作用吗?如果是这样的话我该如何解决呢?

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

#define size 20

void *smallest(void *arg);
pthread_t th, th2;
int array[size], i, min;

int main(int argc, char *argv[]) {

srand ( time(NULL) );
      for(i = 0; i < size; i++)
      {
              array[i] = (rand() % 100)+1;
              printf("%d ", array[i]);
   }

   int *array1 = malloc(10 * sizeof(int));
   int *array2 = malloc(10 * sizeof(int));
   memcpy(array1, array, 10 * sizeof(int));
   memcpy(array2, array + 10, 10 * sizeof(int));

    printf("\nFirst half gives %d \n", *array1);
    printf("Second half gives %d \n", *array2);


    pthread_create(&th, NULL, smallest, (void*) array1);
    pthread_create(&th2, NULL, smallest, (void*) array2);

    pthread_join(th, NULL);
    pthread_join(th2, NULL);

    //printf("\nFirst half gives %d\n", array1);
    //printf("Second half gives %d\n", array2);


if (*array1 < *array2) {
    printf("\nThread1 finds the number\n");
    printf("The smallest element is %i\n", *array1);
}
else {
    printf("\nThread2 finds the number\n");
    printf("The smallest element is %i\n", *array2);
}

return 0;
}

void *smallest(void* arg){

int *array = (int*)arg;

min = array[0];
for (i = 0; i < size; i++) {
  if (array[i] < min) {
     min = array[i];
  }
}
pthread_exit(NULL);
}

3 个答案:

答案 0 :(得分:3)

您设置的代码永远不会运行多个线程。请注意,如果运行if语句的第一个分支,则触发一个线程搜索数组的一半,等待它完成,然后继续向前,如果执行else分支,则在下半部分发生同样的事情。数组。从根本上说,您可能希望通过让代码始终启动两个线程并在两个线程都开始运行后才加入每个线程来重新考虑您的策略。

if语句中的条件似乎也是错误的。您要问的是,数组的中间元素是否大于其索引。我认为这不是你想要做的事情。

最后,每个线程中的代码总是查看整个数组,而不仅仅是它的一半。我建议重写线程例程,使其参数表示范围的起始和结束索引,以取最小值。然后,您将更新main中的代码,以便在启动线程时指定要搜索的范围。

我会构建这样的事情:

  1. 触发线程以找到阵列前半部分的最小值。
  2. 触发线程以找到阵列后半部分的最小值。
  3. 加入两个主题。
  4. 使用每个帖子的结果来查找最小值。
  5. 最后要注意的是,由于您有两个不同的线程,每个线程同时运行,因此当两个线程都尝试读取或写入最小值时,您需要监视数据争用。考虑让每个线程使用其退出代码来指示最小值的位置,然后在main中解析真正的最小值。这消除了竞争条件。或者,有一个全局最小值,但用互斥锁保护它。

答案 1 :(得分:0)

这是您要问的单线程版本。

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

/*
I can not run pthread on my system.
So this is some code that should kind of work the same way
*/
typedef int pthread_t;
typedef int pthread_attr_t;
typedef void*(*threadfunc)(void*);

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg)
{
    start_routine(arg);
    return 0;
}

int pthread_join(pthread_t thread, void **value_ptr)
{
    return 0;
}

struct context
{
    int* begin;
    int* end;
    int* result;
};

//the function has to be castable to the threadfunction type
//that way you do not have to worry about casting the argument.
//be careful though - if something does not match these errors may be hard to track
void * smallest(context * c) //signature needet for start routine
{
    c->result = c->begin;
    for (int* current = c->begin; current < c->end; ++current)
    {
        if (*current < *c->result)
        {
            c->result = current;
        }
    }
    return 0; // not needet with the way the argument is set up.
}

int main(int argc, char *argv[])
{
    pthread_t t1, t2;
#define size 20
    int array[size];
    srand(0);
    for (int i = 0; i < size; ++i)
    {
        array[i] = (rand() % 100) + 1;
        printf("%d ", array[i]);
    }

    //prepare data
    //one surefire way of messing up in multithreading is sharing data between threads.
    //even a simple approach like storing in a variable who is accessing will not solve the issues
    //to properly lock data you would have to dive into the memory model.
    //either lock with mutexes or memory barriers or just don' t share data between threads.
    context c1;
    context c2;
    c1.begin = array;
    c1.end = array + (size / 2);
    c2.begin = c1.end + 1;
    c2.end = array + size;

    //start threads - here your threads would go
    //note the casting - you may wnt to wrap this in its own function
    //there is error potential here, especially due to maintainance etc...
    pthread_create(&t1, 0, (void*(*)(void*))smallest, &c1); //without typedef
    pthread_create(&t2, 0, (threadfunc)smallest, &c2); //without typedef

    pthread_join(t1, 0);//instead of zero you could have a return value here
    pthread_join(t1, 0);//as far as i read 0 throws the return value away
    //return value could be useful for error handling

    //evaluate
    if (*c1.result < *c2.result)
    {
        printf("\nThread1 finds the number\n");
        printf("The smallest element is %i\n", *c1.result);
    }
    else
    {
        printf("\nThread2 finds the number\n");
        printf("The smallest element is %i\n", *c2.result);
    }

    return 0;
}

编辑: 我编辑了一些存根,让您了解如何使用多线程。 我从未使用pthread,但这应该可行。 我使用this源代码获取原型信息。

答案 2 :(得分:0)

1)你在主函数中重新声明了全局变量,所以实际上没有必要声明i,low,high,min:

  

int array [size],i,low,high,min;

当您在main函数中重新声明变量时,您遇到的问题是变量的范围,具有相同名称的全局变量变为“不可见”

   int *low = array;
   int *high = array + (size/2);

   int mid = (*low + *high) / 2;

所以当你运行线程的所有变量值(低,高,分钟; )是0,这是因为它们永远不会被main实际修改,因为它们以0默认(启动代码等)开始。   无论如何,我不会真的推荐(它真的不赞成)使用全局变量,除非它是一个非常小的个人使用的项目。

2)另一个关键问题是你忽略了线程背后的主要思想同时运行

 if (array[mid] > mid) {
    pthread_create(&th, NULL, &smallest, NULL);
    pthread_join(th, NULL);
    printf("\nThread1 finds the number\n");
  }
  else if (array[mid] < mid) {
    pthread_create(&th2, NULL, &smallest, NULL);
    pthread_join(th2, NULL);
    printf("\nThread2 finds the number\n");
  }

实际上你只在执行时运行一个线程。 尝试这样的事情:

pthread_create(&th, NULL, &smallest, NULL);
pthread_create(&th2, NULL, &smallest, NULL);
pthread_join(th2, NULL);
pthread_join(th, NULL);

3)你试图让两个线程访问同一个变量,这可能导致未定义的行为,你必须使用muthex 来避免数字实际上没有被存储。

guide相对于互斥锁非常完整,但如果您需要任何帮助,请告知我们。