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 *restrict tidp 要创建的线程的线程id指针
const pthread_attr_t *restrict attr 创建线程时的线程属性
void* (start_rtn)(void) 返回值是void类型的指针函数
void *restrict arg start_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系统的库,所以在进行编译的时候要加上-lpthread,否则编译不过,会出现下面错误
thread_test.c: 在函数 ‘create’ 中:
thread_test.c:7: 警告: 在有返回值的函数中,程序流程到达函数尾
/tmp/ccOBJmuD.o: In function `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 %d\n",*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 %s\n",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 = %d\n",temp->a);
-
printf(
"menber->s = %s\n",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 = %d\n",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的值的时候,我们新建立的线程则打印出来了改变的值,可以看出可以访问线程所在进程中的数据信息。
2、线程的终止
如果进程中任何一个线程中调用exit,_Exit,或者是_exit,那么整个进程就会终止,
与此类似,如果信号的默认的动作是终止进程,那么,把该信号发送到线程会终止进程。
线程的正常退出的方式:
(1) 线程只是从启动例程中返回,返回值是线程中的退出码
(2) 线程可以被另一个进程进行终止
(3) 线程自己调用pthread_exit函数
两个重要的函数原型:
-
include
-
void pthread_exit(void *rval_ptr);
-
/*rval_ptr 线程退出返回的指针*/
-
-
int pthread_join(pthread_t thread,void **rval_ptr);
-
/*成功结束进程为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$
例程总结:
可以看出来,线程退出可以返回线程的int数值。
线程退出不仅仅可以返回线程的int数值,还可以返回一个复杂的数据结构
-
#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$
-
#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;
-
}
-
"font-family:Arial;BACKGROUND-COLOR: #ffffff">
-
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多线程编程实例解析 - 知秋一叶 - CSDN博客