Linux系统下的多线程遵守POSIX线程插口,称为pthread。编撰Linux下的多线程程序,须要使用头文件pthread.h,联接时须要使用库libpthread.a。顺便说一下,Linux下pthread的实现是通过系统调用clone()来实现的。clone()是Linux所特有的系统调用,它的使用方法类似fork,关于clone()的详尽情况,有兴趣的读者可以去查看有关文档说明。下边我们展示一个最简单的多线程程序pthread_create.c。
一个重要的线程创建函数原型:
#include
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg);
返回值:若是成功构建线程返回0,否则返回错误的编号
方式参数:
pthread_t*restricttidp要创建的线程的线程id表针
constpthread_attr_t*restrictattr创建线程时的线程属性
void*(start_rtn)(void)返回值是void类型的表针函数
void*restrictargstart_rtn的行参
解释器1:
功能:创建一个简单的线程
程序名称:pthread_create.c
代码如下:
#include
#include
void *mythread1(void)
{
int i;
for(i = 0; i < 10; i++)
{
printf("This is the 1st pthread,created by xiaoqiang!n");
sleep(1);
}
}
void *mythread2(void)
{
int i;
for(i = 0; i < 10; i++)
{
printf("This is the 2st pthread,created by xiaoqiang!n");
sleep(1);
}
}
int main(int argc, const char *argv[])
{
int i = 0;
int ret = 0;
pthread_t id1,id2;
ret = pthread_create(&id1, NULL, (void *)mythread1,NULL);
if(ret)
{
printf("Create pthread error!n");
return 1;
}
ret = pthread_create(&id2, NULL, (void *)mythread2,NULL);
if(ret)
{
printf("Create pthread error!n");
return 1;
}
pthread_join(id1,NULL);
pthread_join(id2,NULL);
return 0;
}
执行结果如下:
fs@ubuntu:~/qiang/thread$ vi thread1.c
fs@ubuntu:~/qiang/thread$ gcc -o thread1 thread1.c -lpthread
fs@ubuntu:~/qiang/thread$ ./thread1
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
fs@ubuntu:~/qiang/thread$
两个线程交替执行。
另外,由于pthread的库不是linux系统的库,所以在进行编译的时侯要加上-lpthreadlinux 关机命令,否则编译不过,会出现下边错误
thread_test.c:在函数‘create’中:
thread_test.c:7:警告:在有返回值的函数中,程序流程抵达函数尾
/tmp/ccOBJmuD.o:Infunction`main':thread_test.c:(.text+0x4f):对‘pthread_create’未定义的引用
collect2:ld返回1
此反例介绍了创建线程的方式
下边事例介绍向线程传递参数。
解释器2:
功能:向新的线程传递整形值
程序名称:pthread_int.c
代码如下:
#include
#include
void *create(void *arg)
{
int *num;
num = (int *)arg;
printf("Create parameter is %dn",*num);
return (void *)0;
}
int main(int argc, const char *argv[])
{
pthread_t id1;
int error;
int test = 4;
int *attr = &test;
error = pthread_create(&id1,NULL,create,(void *)attr);
if(error)
{
printf("Pthread_create is not created!n");
return -1;
}
sleep(1);
printf("Pthread_create is created..n");
return 0;
}
执行结果如下:
fs@ubuntu:~/qiang/thread$ vi thread2.c
fs@ubuntu:~/qiang/thread$ gcc -o thread2 thread2.c -lpthread
fs@ubuntu:~/qiang/thread$ ./thread2
Create parameter is 4
Pthread_create is created..
fs@ubuntu:~/qiang/thread$
解释器总结:
可以看下来,我们在main函数中传递的整行表针,传递到我们新建的线程函数中。
在前面的事例可以看下来我们向新的线程传入了另一个线程的int数据,线程之间还可以传递字符串或是更复杂的数据结构。
类库3:
程序功能:向新建的线程传递字符串
程序名称:pthread_string.c
代码如下:
#include
#include
void *create(char *arg)
{
char *str;
str = arg;
printf("The parameter passed from main is %sn",str);
return (void *)0;
}
int main()
{
int error;
pthread_t id1;
char *str1 = "Hello ,xiaoqiang!";
char *attr = str1;
error = pthread_create(&id1, NULL, create, (void *)attr);
if(error != 0)
{
printf("This pthread is not created!n");
return -1;
}
sleep(1);
printf("pthread is created..n");
return 0;
}
执行结果如下:
fs@ubuntu:~/qiang/thread$ ./thread3
The parameter passed from main is Hello ,xiaoqiang!
pthread is created..
fs@ubuntu:~/qiang/thread$
类库总结:
可以看下来main函数中的字符串传入了新建的线程中。
类库4:
程序功能:向新建的线程传递字符串
程序名称:pthread_struct.c
代码如下:
#include
#include
#include
struct menber
{
int a;
char *s;
};
void *create(void *arg)
{
struct menber *temp;
temp = (struct menber *)arg;
printf("menber->a = %dn",temp->a);
printf("menber->s = %sn",temp->s);
return (void *)0;
}
int main()
{
int error;
pthread_t id1;
struct menber *p;
p = (struct menber *)malloc(sizeof(struct menber));
p->a = 1;
p->s = "xiaoqiang!";
error = pthread_create(&id1,NULL,create,(void *)p);
if(error)
{
printf("pthread is not created!n");
return -1;
}
sleep(1);
printf("pthread is created!n");
free(p);
p = NULL;
return 0;
}
执行结果如下:
fs@ubuntu:~/qiang/thread$ vi thread4.c
fs@ubuntu:~/qiang/thread$ gcc -o thread4 thread4.c -lpthread
fs@ubuntu:~/qiang/thread$ ./thread4
menber->a = 1
menber->s = xiaoqiang!
pthread is created!
fs@ubuntu:~/qiang/thread$
类库总结:
可以看下来main函数中的一个结构体传入了新建的线程中。
线程包含了标示进程内执行环境必须的信息。他集成了进程中的所有信息都是对线程进行共享的,包括文本程序、程序的全局显存和堆显存、栈以及文件描述符
类库5:
程序目的:验证新构建的线程可以共享进程中的数据
程序名称:pthread_share.c
代码如下:
#include
#include
static int a = 5;
void *create(void *arg)
{
printf("New pthread...n");
printf("a = %dn",a);
return (void *)0;
}
int main(int argc, const char *argv[])
{
int error;
pthread_t id1;
error = pthread_create(&id1, NULL, create, NULL);
if(error != 0)
{
printf("new thread is not created!n");
return -1;
}
sleep(1);
printf("New thread is created...n");
return 0;
}
结果如下:
fs@ubuntu:~/qiang/thread$ vi thread5.c
fs@ubuntu:~/qiang/thread$ gcc -o thread5 thread5.c -lpthread
fs@ubuntu:~/qiang/thread$ ./thread5
New pthread...
a = 5
New thread is created...
fs@ubuntu:~/qiang/thread$
类库总结:
可以看下来,我们在主线程修改了我们的全局变量a的值的时侯linux 线程 pthread_create,我们新构建的线程则复印下来了改变的值,可以看出可以访问线程所在进程中的数据信息。
2、线程的中止
假如进程中任何一个线程中调用exit,_Exit,或则是_exit,这么整个进程都会中止,
与此类似,假如讯号的默认的动作是中止进程,这么linux 线程 pthread_create,把该讯号发送到线程会中止进程。
线程的正常退出的形式:
(1)线程只是从启动类库中返回,返回值是线程中的退出码
(2)线程可以被另一个进程进行中止
(3)线程自己调用pthread_exit函数
两个重要的函数原型:
include
void pthread_exit(void *rval_ptr);
/*rval_ptr 线程退出返回的指针*/
int pthread_join(pthread_t thread,void **rval_ptr);
/*成功结束进程为0,否则为错误编码*/
pthread_join使一个线程等待另一个线程结束。
代码中若果没有pthread_join主线程会很快结束进而使整个进程结束,因而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会仍然等待直至等待的线程结束自己才结束,使创建的线程有机会执行。
头文件:#include
函数定义:intpthread_join(pthread_tthread,void**retval);
描述:pthread_join()函数,以阻塞的形式等待thread指定的线程结束。当函数返回时,被等待线程的资源被收回。假如线程早已结束,这么该函数会立刻返回。而且thread指定的线程必须是joinable的。
参数:thread:线程标示符,即线程ID,标示惟一线程。retval:用户定义的表针,拿来储存被等待线程的返回值。
返回值:0代表成功。失败,返回的则是错误号。
类库6
程序目的:线程正常退出,接受线程退出的返回码
程序名称:pthread_exit.c
执行代码如下:
#include
#include
#include
void *create(void *arg)
{
printf("new thread is created ... n");
return (void *)0;
}
int main(int argc,char *argv[])
{
pthread_t tid;
int error;
void *temp;
error = pthread_create(&tid, NULL, create, NULL);
if( error )
{
printf("thread is not created ... n");
return -1;
}
error = pthread_join(tid, &temp);
if( error )
{
printf("thread is not exit ... n");
return -2;
}
printf("thread is exit code %d n", (int )temp);
return 0;
}
执行结果如下:
fs@ubuntu:~/qiang/thread$ vi thread6.c
fs@ubuntu:~/qiang/thread$ gcc -o thread6 thread6.c -lpthread
fs@ubuntu:~/qiang/thread$ ./thread6
new thread is created ...
thread is exit code 0
fs@ubuntu:~/qiang/thread$
类库总结:
可以看下来suse linux 下载,线程退出可以返回线程的int数值。
线程退出不仅仅可以返回线程的int数值,还可以返回一个复杂的数据结构
类库7
程序目的:线程结束返回一个复杂的数据结构
代码如下:
#include
#include
#include
struct menber
{
int a;
char *b;
}temp={8,"xiaoqiang"};
void *create(void *arg)
{
printf("new thread ... n");
return (void *)&temp;
}
int main(int argc,char *argv[])
{
int error;
pthread_t tid;
struct menber *c;
error = pthread_create(&tid, NULL, create, NULL);
if( error )
{
printf("new thread is not created ... n");
return -1;
}
printf("main ... n");
error = pthread_join(tid,(void *)&c);
if( error )
{
printf("new thread is not exit ... n");
return -2;
}
printf("c->a = %d n",c->a);
printf("c->b = %s n",c->b);
sleep(1);
return 0;
}
执行结果如下:
fs@ubuntu:~/qiang/thread$ gcc -o thread7 thread7.c -lpthread
fs@ubuntu:~/qiang/thread$ ./thread7
main ...
new thread ...
c->a = 8
c->b = xiaoqiang
fs@ubuntu:~/qiang/thread$
类库总结:
一定要记得返回的数据结构要是在这个数据要返回的结构没有释放的时侯应用,假如数据结构早已发生变化,那返回的就不会是我们所须要的,而是脏数据。
3、线程标示
函数原型:
#include
pthread_tpthread_self(void);
pid_tgetpid(void);
getpid()拿来取得目前进程的进程辨识码,函数说明
解释器8
程序目的:实现在新构建的线程中复印该线程的id和进程id
代码如下:
#include
#include
#include /*getpid()*/
void *create(void *arg)
{
printf("New thread .... n");
printf("This thread's id is %u n", (unsigned int)pthread_self());
printf("The process pid is %d n",getpid());
return (void *)0;
}
int main(int argc,char *argv[])
{
pthread_t tid;
int error;
printf("Main thread is starting ... n");
error = pthread_create(&tid, NULL, create, NULL);
if(error)
{
printf("thread is not created ... n");
return -1;
}
printf("The main process's pid is %d n",getpid());
sleep(1);
return 0;
}
执行结果如下:
fs@ubuntu:~/qiang/thread$ gcc -o thread8 thread8.c -lpthread
fs@ubuntu:~/qiang/thread$ ./thread8
Main thread is starting ...
The main process's pid is 4955
New thread ....
This thread's id is 3075853120
The process pid is 4955
fs@ubuntu:~/qiang/thread$
最后提供一些参考资料
linux多线程编程
循环数组及线性表的应用
linux基础