2012-08-09 131 views
4

我正在通过一些简单的pthread示例形式llnl.computing.gov pthreads教程。网站上的程序打印出threadid的地址,但是我想将id的地址传递给PrintHello,然后使用解引用地址来获取id。我觉得在那里每个线程都应该打印8(线程数)。代码是用HelloWorld与Pthreads损坏的内存

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#define NUM_THREADS 8 

void *PrintHello(void *threadid) 
{ 
    long *taskid = (long *)threadid; 
    sleep(1); 
    printf("Hello from thread %ld\n", *taskid); 
    pthread_exit(NULL); 
} 

int main(int argc, char *argv[]) 
{ 
    pthread_t threads[NUM_THREADS]; 
    int rc; 
    long t; 

    for(t=0;t<NUM_THREADS;t++) { 
    printf("Creating thread %ld\n", t); 
    rc = pthread_create(&threads[t], NULL, PrintHello, (void *) &t); 
    if (rc) { 
     printf("ERROR; return code from pthread_create() is %d\n", rc); 
     exit(-1); 
    } 
} 
pthread_exit(NULL); 
} 

当我在Cygwin编译并运行它时,它seg错误与堆栈损坏错误。如果我重写PrintHello为:

void *PrintHello(void *threadid) 
{ 
    long taskid = (long) threadid; 
    sleep(1); 
    printf("Hello from thread %ld\n", taskid); 
    pthread_exit(NULL); 
} 

不赛格故障,它只是打印的地址,我想取消引用地址和主获得T的值。

有没有人有一些关于如何实现这一目标的指针?我知道我可以通过tpthread_create而不是&t,但我想这样做是为了学习目的。

回答

9

当您从主线程调用pthread_exit(NULL)时,它会终止该线程。此时,main函数中的任何局部变量(包括t)都会被销毁并且不能再使用。

如果在所有工作线程使用t(通过您通过pthread_create传递给它们的指针)完成之前主线程退出,那么您的程序会显示未定义的行为。

该程序包含竞争条件,因为工作线程对变量t的访问以及主线程变量t的销毁未被同步。解决此问题的一种方法是在主线程退出之前,将其与每个工作线程(通过pthread_join)联接。

+0

这很有道理。如果我传递值't',它会起作用,因为那么每个线程都有自己的't'副本,当'Main'时它不会死掉? – CallMeNorm 2012-08-09 20:59:32

+0

正确的是,当您传递某些值_时,您将复制它供被调用者使用。当你传递指针时,指针本身是按值传递的,但指向的东西在调用者和被调用者中都是相同的。 – 2012-08-09 21:01:11

+0

即使你同步他们 - 它不会做你可能想要的。所有的线程可能会打印相同的数字,因为它们使用相同的变量。打印的值将取决于调度 – Gir 2012-08-09 21:46:32

4

1)您通过地址t所以每一个线程将获得一个指向同一个变量,那不是线程ID,它是一个long其具有不断变化的值。您正在修改main中的变量并在每个其他线程(数据竞赛)中读取它。

2)可能发生的情况是,当新线程在main中执行循环时,已经完成并且变量超出了范围。当main退出时,它的局部变量将被弹出堆栈,所以当其他线程访问t时,它不再位于堆栈上。您的程序中没有任何同步来防止这种情况发生,因此您还有另一个数据竞赛。您需要等待main中的线程完成,您可以通过调用pthread_join来等待每个线程完成,但这仍然不会改变其他线程试图在另一线程正在写入时正在读取变量的事实线。

3)有没有必要打电话pthread_exit那里,从功能上还是从主自动返回退出线程(就像调用exit(0)原因main()完)

+0

Btw:主线程的终止不会停止所有其他线程吗? – 2012-08-09 20:40:50

+1

@ H2CO3,我相信如果其他线程仍在运行,调用'pthread_exit'不会终止整个进程。调用'exit'或从'main'返回将导致整个进程停止,即使其他线程正在运行,但是当调用pthread_exit时,进程只会在最后一个线程退出时退出。尽管main中的'pthread_exit'并没有杀死整个进程,变量't'仍然超出了作用域,并且从堆栈中弹出。 – 2012-08-09 20:44:00

0

一些指点?那么,你的线程函数中有很多......

问题:你不能安全地传递你的本地变量的地址 - 它在主要退出时超出范围。您需要将指针声明为静态全局变量或malloc()sizeof(long)字节的内存并使用它。