代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。
#include <pthread.h>
#include <stdio.h>
/* Prints x’s to stderr. The parameter is unused. Does not return. */
void* print_xs (void* unused)
{
while (1)
fputc (‘x’, stderr);
return NULL;
}
/* The main program. */
int main ()
{
pthread_t thread_id;
/* Create a new thread. The new thread will run the print_xs
function. */
pthread_create (&thread_id, NULL, &print_xs, NULL);
/* Print o’s continuously to stderr. */
while (1)
fputc (‘o’, stderr);
return 0;
}
|
int main ()
{
pthread_t thread1_id;
pthread_t thread2_id;
struct char_print_parms thread1_args;
struct char_print_parms thread2_args;
/* Create a new thread to print 30,000 x’s. */
thread1_args.character = ’x’;
thread1_args.count = 30000;
pthread_create (&thread1_id, NULL, &char_print, &thread1_args);
/* Create a new thread to print 20,000 o’s. */
thread2_args.character = ’o’;
thread2_args.count = 20000;
pthread_create (&thread2_id, NULL, &char_print, &thread2_args);
/* Make sure the first thread has finished. */
pthread_join (thread1_id, NULL);
/* Make sure the second thread has finished. */
pthread_join (thread2_id, NULL);
/* Now we can safely return. */
return 0;
}
|
#include <stdio.h>
#include <pthread.h>
void * start_run(void * arg)
{
//do some work
}
int main()
{
pthread_t thread_id;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
pthread_create(&thread_id,&attr,start_run,NULL);
pthread_attr_destroy(&attr);
sleep(5);
exit(0);
}
|
linux 下常用的创建多线程函数pthread_create(pthread_t * thread , pthread_attr_t * attr , void *(*start_routine)(void*) , void *args);其中第一个参数用来保存线程信息,第二个参数指新线程的运行属性,可以设置为NULL,第三个参数为自定义的线程函数,第四个参数就是线程函数需要用到的参数,一般如果要传递多个参数,可以设置为结构体(struct)类型,这里我们使用int类型的变量。 下面我着重讨论一个用for结构来创建多个线程时参数传递的问题 先看下面的例子,后面附有结果,先不要看,猜测一下会有什么样的输出: #include<iostream> 编译运行 g++ -fpermissive args.cc -o args.o -pthread 下面是输出结果,由于线程执行的不确定性,可能你执行的时候得到的结果并非如此,这只是一个代表而已 the id of this thread is 2the id of this thread is 8 the id of this thread is 9 the id of this thread is 9 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 the id of this thread is 20 看到这个结果有没有感觉到有什么不对呢?可能你会感觉到很纳闷,怎么出现了那么多的id=20的结果呢?其实这个认真分析一下并不难理解: 首先pthread_create函数传递的是一个指针型的参数,即传递的是一个地址而已,这样在执行for结构时 for(int i=0; i<th_pop; i++) { pthread_create(&a_thread[i] , NULL , thread_func , &i); } 该块快速执行完成,并且将i置为20,故而传递的地址指向的内容为20,同时其它的线程还没来得及执行 int t_id = *(int*)args;,这样就使得多个线程都指向同一个地址,内容为20,解决该问题的一个办法为中for结构中加入sleep(1),这样当sleep时间大于线程函数执行时间,就可以得到一个正确的结果,不过这种办法剥掉了并发性,并不可取,下面我们采用另一种方法。 我们只修改init()函数 void init() { pthread_mutex_init(&mutex, NULL); int thread_id[th_pop]; for(int i=0; i<th_pop; i++) thread_id[i] = i; for(int i=0; i<th_pop; i++) { int *t = thread_id +i; pthread_create(&a_thread[i] , NULL , thread_func , (void*)t); } //wait the end of the threads; for(int i=0; i<th_pop; i++) { int res = pthread_join(a_thread[i] , NULL); if(res != 0) cout<<"the thread id: "<< i<<" ends fail"<<endl; } pthread_mutex_destroy(&mutex); } 下面输出结果 the id of this thread is 0 the id of this thread is 4 the id of this thread is 2 the id of this thread is 5 the id of this thread is 1 the id of this thread is 3 the id of this thread is 6 the id of this thread is 7 the id of this thread is 8 the id of this thread is 9 the id of this thread is 10 the id of this thread is 11 the id of this thread is 12 the id of this thread is 13 the id of this thread is 14 the id of this thread is 15 the id of this thread is 16 the id of this thread is 17 the id of this thread is 18 the id of this thread is 19 从这个例子中我们应该明白,要避免直接在传递的参数中传递发生改变的量,否则会导致结果不可测 |
pthread_create()函数参数使用心得
发布时间:2005-01-02 02:03:00 来源: ChinaUnix博客 作者: ChinaUnix博客 点击:2693
线程创建函数:
int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void * (*func)(void *), void *arg);
参数func 表示代一个参数void *,返回值也为void *;
对于void *arg,参数传入,在gcc 3.2.2条件下,以下面两种方式传入都可编译通过。
int ssock;
int TCPechod(int fd);
1.pthread_create(&th, &ta, (void *(*)(void *))TCPechod, (void *)ssock);
2.pthread_create(&th, &ta, (void *(*)(void *))&TCPechod, (void *)&ssock);
http://zhidao.baidu.com/question/315398992.html
涉及多参数传递给线程的,都需要使用结构体将参数封装后,将结构体指针传给线程
定义一个结构体struct mypara
{
var para1;//参数1
var para2;//参数2
}
将这个结构体指针,作为void *形参的实际参数传递
struct mypara pstru;
pthread_create(&ntid, NULL, thr_fn,& (pstru));
函数中需要定义一个mypara类型的结构指针来引用这个参数
void *thr_fn(void *arg)
{
mypara *pstru;
pstru = (* struct mypara) arg;
pstru->para1;//参数1
pstru->para2;//参数2
}
pthread_create函数接受的参数只有一个void *型的指针,这就意味着你只能通过结构体封装超过一个以上的参数作为一个整体传递。这是pthread_create函数的接口限定的,别人已经明确表明我只接受一个参数,你硬要塞给他两个肯定会出错了。所以通过结构体这种组合结构变通一下,同样实现了只通过一个参数传递,但通过结构指针对结构数据成员的引用实现多参数的传递
这种用结构体封装多参数的用法不仅仅用在pthread_create函数中,如果你自己设计的函数需要的参数很多〉=5个以上,都可以考虑使用结构体封装,这样对外你的接口很简洁清晰,你的函数的消费者使用起来也很方便,只需要对结构体各个成员赋值即可,避免了参数很多时漏传、误传(参数串位)的问题
结构体内包含结构体完全没有问题,很多应用都这么使用
举例如下:
http://wenku.baidu.com/view/48a302ed6294dd88d0d26b73.html
- #include<stdio.h>
- #include<stdlib.h>
- #include<pthread.h>
- #include<errno.h>
- #include<unistd.h>
- typedef void* (*fun)(void*);
- static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- static pthread_cond_t recv_over = PTHREAD_COND_INITIALIZER;
- static pthread_cond_t decode_over = PTHREAD_COND_INITIALIZER;
- static pthread_cond_t play_over = PTHREAD_COND_INITIALIZER;
- void* receive(void*);
- void* decode(void*);
- void* play(void*);
- pthread_t tdec, tplay, trecv;
- struct mypara
- {
- int thread_id;
- char *thread_name;
- };
- int main(int argc, char** argv)
- {
- struct mypara para;
- para.thread_id = 1;
- para.thread_name = "recv";
- int t1 = 0, t2 = 0, t3 = 0;
- t1 = pthread_create(&trecv, NULL, receive,& (para));
- if(t1 != 0)
- printf("Create thread receive error!\n");
- t2 = pthread_create(&tdec, NULL, decode, NULL);
- if(t2 != 0)
- printf("Create thread decode error!\n");
- t3 = pthread_create(&tplay, NULL, play, NULL);
- if(t3 != 0)
- printf("Create thread play error!\n");
- pthread_join(trecv, NULL);
- pthread_join(tdec, NULL);
- pthread_join(tplay, NULL);
- printf("leave main\n");
- exit(0);
- }
- void* receive(void* arg)
- {
- printf("Start receive\n");
- int i = 0;
- char *s = NULL;
- struct mypara *recv_para;
- recv_para = (struct mypara *)arg;
- i = (*recv_para).thread_id;
- s = (*recv_para).thread_name;
- printf("NO : %d Name : %s\n",i,s);
- sleep(2);
- pthread_mutex_lock(&mutex);
- while (1)
- {
- printf("Receiving...\n");
- sleep(1);
- pthread_cond_signal(&recv_over);
- pthread_cond_wait(&decode_over, &mutex);
- }
- printf("End receive\n");
- pthread_exit(0);
- }
- void* decode(void* arg)
- {
- printf("Start decode\n");
- while (1)
- {
- pthread_cond_wait(&recv_over, &mutex);
- printf("Decoding...\n");
- sleep(1);
- pthread_cond_broadcast(&decode_over); //inform player ready to play
- }
- printf("End decode\n");
- pthread_exit(0);
- }
- void* play(void* arg)
- {
- int ret;
- printf("Start play\n");
- while(1)
- {
- pthread_cond_wait(&decode_over, &mutex); //wait the signal from decoder
- printf("Playing...\n");
- sleep(1);
- }
- pthread_mutex_unlock(&mutex);
- printf("End play\n");
- pthread_exit(0);
- }