如何使用多线程

问题描述 投票:0回答:1

嗨,我有一个关于 pthreads 的问题

我反复测试 pthread_create 和 pthread_join,但似乎传递给函数的参数值没有正确传递

但是,如果我将 sleep() 代码放在 pthread_create 之后,效果很好

不知道为什么会这样,睡眠功能真的有必要吗?

代码:

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

    
void *thread_func(void *arg)
{
    printf("I am thread #%d\n", *(int *)arg);
}

int main(int argc, char *argv[])
{
    pthread_t t1[7];

    while(1){
        for(int i = 0; i < 7; i++){
            pthread_create(&t1[i], NULL, &thread_func, &i);
        }

        sleep(10);
        
        for(int j = 0; j < 7; j++){
            pthread_join(t1[j], NULL);
        }
        
        sleep(10);
    }   

    return 0;
}
int main(int argc, char *argv[])
{
    pthread_t t1[7];

    while(1){
        for(int i = 0; i < 7; i++){
            pthread_create(&t1[i], NULL, &thread_func, &i);
        usleep(1);
        }

        sleep(10);
        
        for(int j = 0; j < 7; j++){
            pthread_join(t1[j], NULL);
        }
        
        sleep(10);
    }   

    return 0;
}
pthreads
1个回答
0
投票

我反复测试 pthread_create 和 pthread_join,但似乎传递给函数的参数值没有正确传递

半信半疑。

但是,如果我将 sleep() 代码放在 pthread_create 之后,效果很好

不知道为什么会这样,睡眠功能真的有必要吗?

调用

sleep()
是解决实际问题的方法。如果您的程序的未定义行为得到了令人满意的解决,那么无论是否调用
sleep()
,它都会产生想要的结果。

问题是,当您将

&i
作为最后一个参数传递给
pthread_create()
时,您会创建一种情况:原始线程和新线程都在查看同一个
int
对象,并且原始线程也在修改该对象在处理连续的循环迭代时。最终,循环范围内的对象的生命周期在循环终止时结束。由于线程之间没有合适的同步,因此程序的行为是未定义的。您的线程可以打印任何线程号,或者您的程序可能崩溃,或者原则上,计算机能力范围内的任何事情都可能发生。

可能的解决方案包括:

  • 为每个线程提供一个指向不同
    int
    对象的指针。例如,
            int args[7];
            for (int i = 0; i < 7; i++){
                args[i] = i;
                pthread_create(&t1[i], NULL, &thread_func, &args[i]);
            }
    
  • 传递
    i
    的值而不是指向
    i
    的指针:
            for (int i = 0; i < 7; i++){
                pthread_create(&t1[i], NULL, &thread_func, (void *) i);
            }
    
    然后线程函数需要将其适当地转换回来:
        printf("I am thread #%d\n", (int) arg);
    
  • 使用适当的同步对象来防止主线程在新线程有机会读取它之前对其进行修改。信号量会很方便,但还有其他可能性:
    i
    同时,当线程函数准备好让主线程继续运行时,它会增加信号量。也许是这样的:
    sem_t startup_sem;
    
    // ...
    
    int main(int argc, char *argv[]) {
        sem_init(&startup_sem, 0, 0);
    
        // ...
         for(int i = 0; i < 7; i++){
             pthread_create(&t1[i], NULL, &thread_func, &i);
             sem_wait(&startup_sem);
         }
    
         // ...
    
    
        
© www.soinside.com 2019 - 2024. All rights reserved.