pthreads程序表现不佳

时间:2013-12-24 11:02:53

标签: c linux multithreading pthreads posix

我正在尝试使用pthreads创建一个简单的程序,想要制作6个线程并将索引传递给所有这些线程。这是代码:

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

#define num_students 6

void thread_starter();

int main() {
    pthread_t thread1[num_students];

    int i = 0;
    for(i = 0; i<num_students; i++) {
        int q = i;
        pthread_create(&thread1[i], NULL, (void *) &thread_starter, (void *)&q);
        }
    sleep(1);
}


void thread_starter(void* a) {
    printf("Thread %i \n", *((int*)a));
}

输出:

Thread 2
Thread 3 
Thread 2 
Thread 4 
Thread 5 
Thread 5 

为什么他们有通用名字?怎么了?

由于

3 个答案:

答案 0 :(得分:2)

您将堆栈地址从主线程传递到所有子线程。无法保证何时安排这些线程,因此您无法知道主线程是否会在每个孩子阅读它时更新其堆栈变量。

为避免这种情况,您需要为传递给每个线程的数据分配内存。

在您的示例中执行此操作的最简单方法是使用另一个自动变量来存储传递给新线程的数据

void thread_starter(void* a);
int main() {
    pthread_t thread1[num_students];
    int thread_data[num_students];
    int i = 0;
    for(i = 0; i<num_students; i++) {
        thread_data[i] = i;
        pthread_create(&thread1[i], NULL, thread_starter, &thread_data[i]);
    }
    sleep(1);
}

另请注意,如果您在前方声明中给出正确的签名,则可以避免必须投射thread_starter

对于更复杂的程序,您可能需要为每个线程动态分配内存,将该内存的所有权传递给新线程。

int main() {
    pthread_t thread1[num_students];
    int i = 0;
    for(i = 0; i<num_students; i++) {
        int* data = malloc(sizeof(*data));
        *data = i;
        pthread_create(&thread1[i], NULL, thread_starter, data);
    }
    sleep(1);
}

void thread_starter(void* a) {
    printf("Thread %i \n", *((int*)a));
    free(a);
}

最后,使用sleep(1)并不是一种确保所有线程都能运行的非常严格的方法。最好使用pthread_join代替

for(i = 0; i<num_students; i++) {
    pthread_join(thread1[i], NULL);
}

答案 1 :(得分:1)

sleep不是等待衍生线程的正确工具,请使用pthread_join

你的main函数终止等同于为整个程序调用{​​{1}}并杀死所有其他线程。

答案 2 :(得分:1)

尝试使用此变体

void thread_starter(void* a) {
// Put a sleep(1) Here and see you will get even bizarre results
printf("Thread %i \n", *((int*)a));
}

好的,这里的问题当然是

此时

竞争条件

int q = i;
pthread_create(&thread1[i], NULL, (void *) &thread_starter, (void *)&q);

假设创建了第一个线程,q处的值为0

现在假设在执行语句之前

printf("Thread %i \n", *((int*)a));

如果主线程进一步循环并在此处执行此语句

int q = i;

再次,然后q值改变(因为它的参考)因此问题

一种避免这种情况的方法是在线程例程中的本地变量中复制此引用变量也使用互斥锁。

对不起,我很快就从我这边得到了一些提示

#define num_students 6
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  // A Global Mutex

将在这里取得锁定

    pthread_mutex_lock( &mutex );
    printf("\n Got Mutex %d\n", i);
    int q = i;
    pthread_create(&thread1[i], NULL, (void *) &thread_starter, (void *)&q);

并将在子例程中释放锁定

int i = *((int*)a);
sleep(1);
pthread_mutex_unlock( &mutex );
printf("Thread %i \n", i);

P.S - 在不适用的地方删除不必要的版画和睡眠