2011-06-03 94 views
2

我的问题是与C中的线程编程有关。 我的问题是我只是想在我的主程序中创建两个线程。这两个线程应该顺序工作,这意味着我的第一个线程应该首先执行(不应该执行任何线程的其他语句)。第一个线程应该完全控制。在第一个线程完成之前,不应该执行任何其他线程的其他语句,甚至是主程序语句。C语言和多线程编程

完成第一个线程后,应该以与第一个线程类似的方式执行第二个线程。

之后,我的主要执行。

我知道你可以说为什么我要这样做,因为这个事情可以通过创建两个函数并按顺序调用它来实现,但为了学习和实验,我希望在线程。

我写一些C代码如下:

void* fun() 
{ 
    printf("\nThe thread 1 is running"); 
} 
void* van() 
{ 
    printf("\nthread 2 is running "); 
} 

int main() 
{ 
    pthread_t t1,t2; 
    pthread_create(&t1,NULL,fun,NULL); 
    pthread_create(&t2,NULL,van,NULL); 
    printf("\nI'm in main\n"); 
    pthread_join(t2,NULL); 
} 

程序的工作完美,但我不理解的功能pthread_join()的工作。

当我改变我的代码有点如下:

int main() 
{ 
    pthread_t t1,t2; 
    pthread_create(&t1,NULL,fun,NULL); 
    pthread_join(t2,NULL); // Change 
    pthread_create(&t2,NULL,van,NULL); 
    printf("\nI'm in main\n"); 
} 

现在,当我运行的代码它显示了一个分段错误。

现在我的问题有以下几点:

  1. 中有什么pthread_create()功能的属性参数?我们为什么要使用它们?线程的默认属性是什么?请用一个例子来解释。
  2. pthread_create()函数中的参数是什么?我们为什么使用它们?线程的默认参数是什么?请用一个例子来解释。
  3. pthread_join()如何实际工作?当我的代码主要使用pthread_join()作为第一个参数t2时,这意味着什么。这是否意味着main应该暂停执行,直到t2执行完成或其他什么东西?
  4. pthread_join()中的第二个参数是什么?我们为什么用它?它的默认值是多少?请用一个例子或代码来解释。
+1

你的线程函数应该返回一个值,即使它只是零,以便它们返回一个空的void指针。在“工作”代码中,按照您的意图进行排序纯粹是巧合。两个线程函数并发执行; 'main()'不会等待线程1在启动线程2之前完成。如果等待线程1完成('pthread_join(&t1,NULL);'在其'pthread_create()'后面,那么会最小化并发执行重复执行线程2.然后你可以在'main()'本身运行'printf()',因为你已经等待每个线程完成了,你就完成了。 – 2011-06-03 05:49:37

回答

7
  1. 的ATTR参数指向一个pthread_attr_t结构,其内容在线程创建时被用来确定为新的线程属性;该结构使用pthread_attr_init(3)和相关功能进行初始化。如果attr为NULL,则使用默认属性(source)创建该线程。

  2. 将参数传递给您的线程函数。这是将数据传递给线程的最佳方式(与使用全局变量相反,例如)。

  3. 是的,pthread_join一直等到线程结束。这就是为什么当你在启动线程之前调用pthread_join时程序失败,因为t2包含那个点的垃圾。

  4. 如果RETVAL不是NULL,则在pthread_join()拷贝目标线程的退出状态(即,提供给了pthread_exit目标线程(3)的值)到位置由* RETVAL指向。如果目标线程被取消,则PTHREAD_CANCELED被放置在* retval中。 (source)。

即,你可以让你的线程函数来通知你关于它的执行结果。

鉴于此,您的线程创建可能是这样的:

struct th_arg{ 
    ... 
}; 

static void th_work(struct th_arg* a){ 
    //...some work 
    if (success) pthread_exit(EXIT_SUCCESS) 
    else pthread_exit(ERROR_CODE); 
} 

int main(){ 
    int t1,t2; 
    struct th_arg[2]; 
    int codes[2]; 
    // initialize th_arg2 
    pthread_create(&t1, NULL, th_work, th_arg+0, th_arg+0); 
    pthread_create(&t2, NULL, th_work, th_arg+1, th_arg+1); 
    pthread_join(t1, codes+0); 
    pthread_join(t2, codes+1); 

    if (codes[0] == EXIT_SUCCESS && codes[1] == EXIT_SUCCESS){ 
      ... 
    } 
} 
1
  • pthread_create属性是pthread_attr_t类型。它保存有关线程的信息,包括线程内存地址开始的位置以及堆栈的大小等信息。大多数时候你不需要使用这个参数。

  • pthread_create中的arg被作为唯一的参数传递给start_routine函数。这是一种黑客。由于指针可以指向任何东西(int,数组,结构体等),因此可以通过将指针传递给要传入的所有数据来传递参数。大多数情况下,人们最终都会使用一个结构。线程没有默认参数。如果你不想传入任何东西,只需指定arg为NULL。

作为一个例子:

struct arguments 
{ 
    int something; 
    char* anotherArg; 
    short stillAnotherArg; 
} 

void* fun(void* arg) 
{ 
    struct arguments *my_args = (struct arguments*)arg; 
    printf("You said: %s\n", my_args->anotherArg); // Will print "You said: Hello there" 
    ... 
} 

int main() 
{ 
    pthread_t t1; 

    struct arguments my_args; 
    my_args.something = 5; 
    my_args.anotherArg = "Hello there"; 
    my_args.stillAnotherArg = 42; 

    pthread_create (&t1,NULL,fun, &my_args); 
    ... 
} 
  • pthread_join块呼叫者直到指定线程完成。

  • pthread_join的第二个参数允许您在完成执行后捕获线程的返回值。每个线程返回一个void*,第二个参数允许您指定返回值的存储位置。

举个例子:

void* fun(void* arg) 
{ 
    ... 
    return NULL; // not very exciting, but I don't want to get 
       // into memory management problems right now 
} 

int main() 
{ 
    ... 

    void* theReturnValue; 
    pthread_join(t2, &theReturnValue); 

    printf("fun returned %p\n", theReturnValue); // will print "fun returned 0x0" 
               // which is NULL 
} 

最后,它出现segfaults的原因是因为你在等待的尚未定义的线程。