线程的一些概念
来源:互联网 发布:云数据交换 软硬一体 编辑:程序博客网 时间:2024/06/08 20:03
线程是操作系统能够进行运算调度的最小单位,包含在进程之中。典型的UNIX/Linux进程可以看做只有一个控制线程。
线程包含了表示进程内执行环境必须的信息,其中包括进程中标识线程的线程ID、一组寄存器值、栈、调度优先级和策略、信号屏蔽字、errno变量以及线程私有数据(没有独立的堆,共享堆)。进程内所有信息对该进程内的线程都是共享的,包括可执行的程序文本、程序的全局内存和堆内存、栈以及文件描述符。
线程标识
像进程ID一样,每个线程也有一个线程ID。进程ID在整个系统中是唯一的,但线程ID只在它所属的进程内有效。线程ID是用pthread_t数据类型表示,实现的时候可以用一个数据结构来代表pthread_t数据类型,所以在可移植的操作系统不能把它作为整数处理。因此两个线程ID比较的话,必须是用函数
#include<pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);
获取自己ID可以用
#incude<pthread.h>
pthread_t pthread_self(void);
线程创建
在创建线程先,可以认为进程中只有一个主控线程。创建线程可以使用
#include<pthread.h>
int pthread_create(pthread_t *restrict tidp,
const pthread_attr_t *restrict attr.
void *(*start_rtn)(void *), void *restrict arg);
当线程创建成功返回时,tidp指向的内存单元被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性。
新创建的线程从start_rtn函数地址开始运行,该函数之后一个无类型指针参数arg,如果要传入多个参数,那么就要把多个参数做成结构体,然后传入结构体。
线程创建后不能保证哪个线程先运行:是新创建的还是调用线程。新创建的线程可以访问进程的地址空间,继承调用线程的浮点环境和信号屏蔽字,但是该线程的未决信号集被清除。
pthread失败时会返回错误码,不像其他POSIX函数一样设置errno。每个线程都提供errno副本,这只是为了与使用errno的现有函数兼容。
可以通过下面代码测试一下,功能为打印线程ID
#include<pthread.h>pthread_t ntid;voidprintids(const char *s){pid_t pid;pthread_t tid;pid=getpid();tid=pthread_self();printf("%s pid %u tid %u (0x%x)\n",s,(unsigned int)pid,(unsigned int)tid,(unsigned int)tid);}void*thr_fn(void *arg){printids("new thread:");return ((void*)0);}int main(void){int err;err=pthread_create(&ntid,NULL,thr_fn,NULL);if(err!=0)printf("can't create thread:%s\n",strerror(err));printids("main thread:");sleep(1);exit(0);}
在Fedora上面运行结果为:
main thread: pid 3922 tid 3078109440 (0xb7783900)
new thread: pid 3922 tid 3078105920 (0xb7782b40)
sleep(1)的目的是防止主线程结束。通过pthread_self获取线程ID,因为在pthread_create在返回前,函数可能就已经运行了。
线程终止
一个进程中的任何一个线程调用exit,_exit,_Exit整个进程都会终止。如果信号默认动作是终止进程,那么,把该信号发送给线程也会终止进程。
终止单个线程可以通过以下方法:
1、线程只是从启动例程中返回,返回值是线程退出码。
2、线程被同一进程中的其他线程取消。
3、调用pthread_exit
#include<pthread.h>
void pthread_exit(void *rval_ptr)
其中rval_ptr是一个无类型指针,和传给启动例程参数类似。同一进程中的其他进程可以调用pthread_join函数获得这个指针。
#include<pthread.h>
void pthread_join(pthread_t thread, void **rval_prt);
其中要注意一点,就是线程退出状态的值,不能再线程的栈上。如果在栈上,当线程退出后,栈空间就释放了。
线程可以取消同一进程中的其他线程
#include<pthread.h>
int pthread_cancel(pthread_t tid)
线程可以注册在退出时调用的清理函数,类似进程的atexit,处理程序记录在栈中,因此调用顺序与注册顺序相反
#inlcude<pthread.h>
void pthread_cleanup_push(void (*rtn) (void *), void *arg);
void pthread_cleanup_pop(int execute);
写代码测试一下上面的几个函数:
#include<pthread.h>void cleanup(void *arg){printf("cleanup:%s\n",(char *)arg);}void* thr_fn1(void *arg){printf("thread 1 start\n");pthread_cleanup_push(cleanup,"thread 1 first handler");pthread_cleanup_push(cleanup,"thread 1 second handler");printf("thread 1 push complete\n");if(arg)pthread_exit((void*)1);pthread_cleanup_pop(0);pthread_cleanup_pop(0);pthread_exit((void*)1);}void* thr_fn2(void *arg){printf("thread 2 start\n");pthread_cleanup_push(cleanup,"thread 2 first handler");pthread_cleanup_push(cleanup,"thread 2 second handler");printf("thread 2 push complete\n");if(arg)return (void*)2;pthread_cleanup_pop(0);pthread_cleanup_pop(0);return (void*)2;}int main(void){pthread_t tid1, tid2;void *tret;pthread_create(&tid1,NULL,thr_fn1, (void *)1);//创建线程1pthread_create(&tid2,NULL,thr_fn2, (void *)1);//创建线程2//获取线程退出状态pthread_join(tid1, &tret);//阻塞,直到线程1退出printf("thread 1 exit code %d\n", (int)tret);//直接把指针转换为intpthread_join(tid2, &tret);//阻塞,直到线程2退出printf("thread 2 exit code %d\n", (int)tret);exit(0);}
在Fedora上面运行结果为:
thread 2 start
thread 2 push complete
thread 1 start
thread 1 push complete
cleanup:thread 1 second handler
cleanup:thread 1 first handler
thread 1 exit code 1
thread 2 exit code 2
- 线程的一些概念
- 关于线程的 一些概念
- Java:线程同步的一些概念
- day1:关于线程的一些概念
- GCD的应用 及线程的一些概念
- Java中线程和进程的一些概念的理解
- 操作系统中进程和线程的一些概念
- 关于线程的一些概念和关于线程返回值的简单示例代码
- Java 线程知识(一)---线程一些概念的简单介绍
- 线程的相关概念
- 线程的概念
- 线程的概念
- Java线程的概念
- 线程的概念
- 线程的概念
- 线程的概念&操作
- Java线程的概念
- 线程安全的概念
- 【Andorid开发框架学习】之Mina开发之客户端开发
- 正益无线赵庆华:AppCan助力开发者轻装前行
- jenkins安装和使用(一)
- android学习笔记 按电源键屏幕唤醒和屏幕睡眠流程(从上层到kernel)
- Windows ListCtrl使用技巧
- 线程的一些概念
- C#记事本(含汉字,字母统计)
- 配置freeglut和glew
- STC EEPROM排列表
- java 对reids的操作 切片与非切片连接池的应用
- Axure RP7.0教程 部件详解 动态面板 DynamicPanel
- 字符串匹配
- html Div层的展开与收缩的特效
- Android睡眠唤醒机制--Kernel态