POSIX多线程之创建线程pthread_create && 线程清理pthread_cleanup
pthreads定义了一套C程序语言类型、函数、与常量。以pthread.h和一个线程库实现。
数据类型:
pthread_t:线程句柄
pthread_attr_t:线程属性
线程操作函数:
pthread_create():创建一个线程
pthread_exit():终止当前线程
pthread_cancel():中断另外一个线程的运行
pthread_join():阻塞当前的线程,直到另外一个线程运行结束
pthread_attr_init():初始化线程的属性
pthread_attr_setdetachstate():设置脱离状态的属性
pthread_attr_getdetachstate():获取脱离状态的属性
pthread_attr_destroy():删除线程的属性
pthread_kill():向线程发送一个信号
.....
创建线程:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_rtn) (void*),void *arg);
*thread:线程id (指向线程标识符的指针)
*attr:线程属性(通常为空)
*start_rtn:线程要执行的函数(线程运行函数的起始地址)
*arg:start_rtn的参数
返回值为零才算成功,其它表示错误
编译时需要加上 -lpthread库
示例一:
#include <stdio.h>
#include <pthread.h>
void *pthread_1(void) //线程1执行的函数
{
inti;
for(i=1; i < 5; i++){
printf("pthread1.\n");
sleep(1);
}
return (void *)0;
}
void *pthread_2(void) //线程2执行的函数
{
inti;
for(i=1;i < 5; i++){
printf("pthread2.\n");
sleep(1);
}
return (void *)0;
}
int main(int argc, char argv[])
{
intret = 0;
pthread_tpthid1, pthid2; //线程的id
ret= pthread_create(&pthid1,NULL, (void *)pthread_1, NULL);
if(ret) // 非0则创建失败
{
perror("createthread 1 failed.\n");
return1;
}
ret= pthread_create(&pthid2, NULL, (void *)pthread_2, NULL);
if(ret)
{
perror("createthread 2 failed.\n");
return1;
}
pthread_join(pthid1,NULL); //等待pthid1,否则不会等待,继续往下执行
pthread_join(pthid2,NULL); //如无,遇到下面的return会结束进程
return0;
}
示例二:传递参数,初始化
/*
*pthread_init.c
*
* Created on: Jan 20, 2013
* Author: linuxdba@qq.com
*/
#include <stdio.h>
#include <pthread.h>
void *create(void *arg)
{
int *num;
num = (int*)arg;
printf("theinput number is: %d.\n", *num);
return(void *)0;
}
int main(int argc, char argv[])
{
intret;
intt;
printf("Inputone number:");
scanf("%d",&t);
int*attr = &t;
pthread_tpthid;
ret= pthread_create(&pthid, NULL, (void *)create, (void *)attr);
if(ret)
{
perror("createthread failed.\n");
return1;
}
pthread_join(pthid,NULL);
return0;
}
示例三:共享数据
/*
*pthread_share.c
*
* Created on: Jan 20, 2013
* Author: linuxdba@qq.com
*/
#include <stdio.h>
#include <pthread.h>
static int i = 3;
void *pthread_1(void)
{
printf("thread1, i is: %d.\n", i);
return(void *)0;
}
void *pthread_2(void)
{
printf("thread2, i is: %d.\n", i);
return(void *)0;
}
int main(int argc, char argv[])
{
intret = 0;
inti = 5;
pthread_tpthid1, pthid2;
printf("mainthread, i is: %d.\n", i);
ret= pthread_create(&pthid1, NULL, (void *)pthread_1, NULL);
if(ret)
{
printf("createthread 1 failed.\n");
return1;
}
ret= pthread_create(&pthid2, NULL, (void *)pthread_2, NULL);
if(ret)
{
printf("createthread 2 failed.\n");
return1;
}
pthread_join(pthid1,NULL);
pthread_join(pthid2,NULL);
return0;
}
此段程序之中两个线程是对等的,不存在先后顺序;
i 为全局变量,main函数内部为局部的变量。
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_create.3.html
http://baike.baidu.com/view/974776.htm
线程清理:pthread_cleanup_push() & pthread_cleanup_pop()
A cancellation clean-up handler is poppedfrom the stack and executed in
The following circumstances:(三种情况会执行线程清理)
1. When a thread is canceled, allof the stacked clean-up handlers are popped and executed in the reverse of theorder in which they were pushed onto the stack. (线程取消)
2. When a thread terminates bycallingpthread_exit(3),all clean-up handlers are executed as described in the preceding point. (Clean-up handlers are not called if thethread terminates by performing a return from the thread start function.) (push与pop之间执行了pthread_exit)
3. When a thread calls pthread_cleanup_pop()with a nonzero execute argument, the top-most clean-up handler is popped andexecuted.(pop内为非零参数)
示例代码:
/*
*pthread_push_pop.c
*
* Created on: Jan 21, 2013
* Author: linuxdba@qq.com
*/
#include <stdio.h>
#include <pthread.h>
void *clean1(void *arg)
{
printf("clean1func: %s\n", arg);
return(void *)0;
}
void *clean2(void *arg)
{
printf("clean2func: %s\n", arg);
return(void *)0;
}
void *thread(void )
{
pthread_tthid;
thid= pthread_self(); //获取线程ID
printf("thethread is: %d.\n",thid);
printf("theprocess id is: %d.\n", getpid()); //进程ID
pthread_cleanup_push((void*)clean1,"first push");
pthread_cleanup_push((void*)clean2, "second push");
printf("Inthread.\n");
pthread_exit("threadexit.\n"); //退出线程,会执行push指定函数
/*return NULL; */ //不会执行push指定函数
pthread_cleanup_pop(0);//为0,只有在异常退出时才会执行push指定的函数,pop第一个
pthread_cleanup_pop(1);//为非0,即便是正常,也会执行push指定的函数,pop第二个
returnNULL;
}
int main(int argc, char argv[])
{
intret = 0;
pthread_tpthid;
ret= pthread_create(&pthid, NULL,(void *)thread,NULL);
if(ret)
{
printf("createthread failed.\n");
return-1;
}
printf("theprocess is: %d.\n", getpid()); //获取进程ID
pthread_join(pthid,NULL);
}
运行结果:
the process is: 3893.
the thread is:1738999552.
the process id is: 3893.
In thread.
clean2 func: second push
clean1 func: first push
push与pop采用栈方式,先进后出,后进先出,所以clean2会在前面。
需要注意的几点:
1) 线程属于进程的,只有一个进程ID,一样的;
2) push和pop是采用栈方式;
3) pthread_cleanup_pop后面为0则执行push指定函数,非0则即便正常也执行
4) push与pop之间代码若异常退出,包括pthread_exit,会进行相应的函数处理,但是若其间执行了return,则直接结束线程,不执行push指定函数。
参考文档:
http://man7.org/linux/man-pages/man3/pthread_cleanup_push.3.html
POSIX多线程之创建线程pthread_create && 线程清理pthread_cleanup的更多相关文章
- C++ Linux 多线程之创建、管理线程
线程就是,在同一程序同一时间内同意运行不同函数的离散处理队列. 这使得一个长时间去进行某种特殊运算的函数在运行时不阻碍其它的函数变得十分重要. 线程实际上同意同一时候运行两种函数,而这两个函数不必相互 ...
- 7、Java并发性和多线程-如何创建并运行线程
以下内容转自http://ifeve.com/creating-and-starting-java-threads/: Java线程类也是一个object类,它的实例都继承自java.lang.Thr ...
- Java多线程的创建(一)
方法一:继承Thread类实现 1.创建一个类A,并继承Thread类 2.重写A的run()方法 3.创建A的实例对象b,即创建了线程对象 4.使用b调用start()方法:启动线程(会自动调用ru ...
- POSIX多线程—线程基本概念
http://blog.csdn.net/livelylittlefish/article/details/7957007 作者:阿波链接:http://blog.csdn.net/livelylit ...
- iOS开发多线程篇—创建线程
iOS开发多线程篇—创建线程 一.创建和启动线程简单说明 一个NSThread对象就代表一条线程 创建.启动线程 (1) NSThread *thread = [[NSThread alloc] in ...
- POSIX多线程——基本线程管理函数介绍
POSIX基本的几个线程管理函数见下表: ------------------------------------------------------------------------------- ...
- posix多线程--线程取消
1.三种取消状态Off 禁用取消Deferred 推迟取消:在下一个取消点执行取消Asynchronous 异步取消:可以随时执行取消 in ...
- posix多线程--三种基本线程编程模型
本文介绍了三种构建线程解决方案的方式. 一.流水线:每个线程执行同一种操作,并把操作结果传递给下一步骤的线程. 代码示例如下:终端输入一个int值,每个线程将该值加1,并将结果传给下一个线程. #in ...
- java多线程-概念&创建启动&中断&守护线程&优先级&线程状态(多线程编程之一)
今天开始就来总结一下Java多线程的基础知识点,下面是本篇的主要内容(大部分知识点参考java核心技术卷1): 1.什么是线程以及多线程与进程的区别 2.多线程的创建与启动 3.中断线程和守护线程以及 ...
随机推荐
- UICachedDeviceRGBColor CGImage]: unrecognized selector sent to instance 0xxxxxxxxxxx'
UICachedDeviceRGBColor CGImage]: unrecognized selector sent to instance 0xxxxxxxxxxx' 报错原因是 本来应该写空间的 ...
- Golang常见小细节总结(1)
本系列不定期更新,用于记录平常开发过程中出现的一些小问题 Array 类型的值作为函数参数    可以理解slice是对array的一个视图,底层还是array所以会被修改 通过map的ok来确 ...
- 【WPF】修改ListBox的Item的样式
<ListBox> <!-- 数据 --> <ListBoxItem>AAAA</ListBoxItem> <ListBoxItem>BB& ...
- 【SpringBoot】SpringBoot日志框架(四)
日志框架介绍 在开发过程中,我们经常使用到日志来进行排查问题,我们使用的日志框架都是由2部分组成(日志API + 日志实现) 日志API(及日志抽象层)有:SLF4j(Simple Logging F ...
- tomcat安全基线
为了符合tomcat安全基线,需要做一下加固: 1.管理用户的密码加密:<摘要算法加密tomcat登录密码> 管理用户在conf/tomcat-users.xml中配置,密码一般是明文形式 ...
- win7安装 truffle
1. 最近有个项目需要用到区块链,第一次玩不太熟悉.现在电脑上安装个 truffle,作为一个区块链节点 2. 安装 truffle ,之前需要安装其他几个软件 truffle的安装需要首先装有:n ...
- Linux 就该这么学 CH03 管道符、重定向和环境变量
0 概述 1 输入输出重定向 重定向技术有5种模式: 标准覆盖输出重定向 标准追加输出重定向 错误覆盖输出重定向 错误追加输出重定向 输入重定向 输入重定向是将文件导入到命令中. 输出重定向是将输入到 ...
- Google BERT摘要
1.BERT模型 BERT的全称是Bidirectional Encoder Representation from Transformers,即双向Transformer的Encoder,因为dec ...
- MySQL ALTER TABLE语法
先看一下定义(密密麻麻) ALTER TABLE tbl_name [alter_specification [, alter_specification] ...] [partition_optio ...
- javascript中 for in 、for 、forEach 、for of 、Object.keys().
一 .for ..in 循环 使用for..in循环时,返回的是所有能够通过对象访问的.可枚举的属性,既包括存在于实例中的属性,也包括存在于原型中的实例.这里需要注意的是使用for-in返回的属性因各 ...