POSIX多线程程序设计学习篇之一(线程管理)
来源:互联网 发布:李氏筋骨散淘宝 编辑:程序博客网 时间:2024/05/21 09:54
首先来一份最简单的开胃篇代码来认识多线程
#include<pthread.h>#include<stdio.h>void *thread_routine(void *arg)//子线程执行的函数{ printf("son thread\n"); int i = 0; for(i = 0; i<100; i++) printf("i =%d\n",i); return arg;}void main(int argc,char *argv[]){ int a = 0; printf("a = %d\n",a); pthread_t thread_id; void *thread_result; int status; status = pthread_create(&thread_id,NULL,thread_routine,NULL);//创建子线程 if(status != 0) printf("create thread error"); else printf("create thread success%ld\n",(unsigned long)thread_id); status = pthread_join(thread_id,&thread_result);//阻塞主线程,直到子线程执行完毕。}
一,Pthread API 命名约定如下:
二,线程的创建、退出等函数介绍
pthread_create(thread,attr,function,arg)//线程的创建(线程结构变量,属性,线程函数入口,线程函数参数)
pthread_exit(status)
pthread_attr_init(attr)
pthread_attr_destroy(attr)
一个进程可以创建的线程最大数量取决于系统实现
线程属性:
- 线程被创建时会带有默认的属性。其中的一些属性可以被程序员用线程属性对象来修改。
- pthread_attr_init 和 pthread_attr_destroy用于初始化/销毁先前属性对象。
- 其它的一些函数用于查询和设置线程属性对象的指定属性。
- 其他等等
结束终止:
a, 线程从主线程(main函数的初始线程)返回。
b, 线程调用了pthread_exit函数,显示的退出当前线程。
c, 其它线程使用 pthread_cancel函数结束线程。
d, 调用exec或者exit函数,整个进程结束。
如果main()在其他线程结束前用pthread_exit()退出了,其他线程将会继续执行。否则,他们会随着main的结束而终止。
三,链接和分离
1,在任何一个时间点上,线程是可结合的(joinable),或者是分离的(detached)。joinable:能够被其他线程收回其资源和杀死;在被其他线程回收之前,系统资源是不释放的。
当pthread_join()函数返回时,创建的线程才算终止。(系统默认)
detached:不能被其他线程回收或杀死的,系统资源在它终止时由系统自动释放。
线程的分离状态决定一个线程以什么样的方式来终止自己。在默认情况下线程是非分离状态的。
2,常用函数如下:
(1)线程的阻塞和分离
int pthread_join(pthread_t tid, void**thread_return); //阻塞本地线程,直到设置的线程tid执行结束。
int pthread_detach(pthread_t tid); //设置分离状态的方式
为了避免存储器泄漏,每个可结合线程都应该要么被显示地回收,即调用pthread_join;要么通过调用pthread_detach函数被分离。
(2)设置和获得分类状态
pthread_attr_setdetachstate (attr,detachstate)
pthread_attr_getdetachstate (attr,detachstate)
其中detachstate参数可选为PTHREAD_CREATE_DETACHED(分离线程)和 PTHREAD _CREATE_JOINABLE(非分离线程)
(3)分离线程有个问题是,可能在pthread_create函数返回之前就终止了,就可能将线程ID和系统资源移交给其他的线程使用,
这样当前调用pthread_create的线程就得到了错误的线程号。(可以在被创建的线程里调用pthread_cond_timewait函数避免)
3,设置分离状态的方式
(1)调用 pthread_detach()函数
(2)创建线程时就将线程属性设置为detached 状态
首先声明pthread_attr_t attr;
然后初始化attr---pthread_attr_init(&attr);
再然后设置线程类别---pthread_attr_setdetachstate(&attr,detachstatus);
最后线程create完毕后释放attr--pthread_attr_destroy(&attr);
下面例子足以说明以上信息
#include <pthread.h> #include <stdio.h> #define NUM_THREADS (3) #define JOIN_TO_DETACH (1)//三个宏只有一个能为1,测试三种情况#define ONLY_JOIN (0)#define ONLY_DETACH (0)void *fun(void *arg) { #if JOIN_TO_DETACH int status = pthread_detach(pthread_self()); printf("detach %d status= %x\n",((int*)arg)[0], (long)status); #endif int i = 0; for (i=0; i<5; i++) { printf("id = %d result = %d\n",((int*)arg)[0],i); sched_yield();//将处理器交给另一个等待的程序 } //pthread_exit(NULL); } int main (int argc, char *argv[]) { pthread_t thread[NUM_THREADS]; pthread_attr_t attr; int a[NUM_THREADS][1]; int i; int status = 0; pthread_attr_init(&attr);#if JOIN_TO_DETACH || ONLY_JOIN pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); //设置成结合属性#else pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); #endif for(i=0; i<NUM_THREADS; i++) { a[i][0] = i; printf("Creating thread %d\n", i); pthread_create(&thread[i], &attr, fun, a[i]); } pthread_attr_destroy(&attr); #if ONLY_JOIN || DETACH_TO_JOIN for(i=0; i<NUM_THREADS; i++) { status = pthread_join(thread[i],NULL); printf("join %d status= %x\n",i, (long)status); } #endif pthread_exit(NULL); return 0;}
四,栈管理
pthread_attr_getstacksize (attr, stacksize)
pthread_attr_setstacksize (attr, stacksize)
pthread_attr_getstackaddr (attr, stackaddr)
pthread_attr_setstackaddr (attr, stackaddr)
可以被程序用于将栈设置在指定的内存区域
五,补充
1,线程ID
pthread_equal (thread1,thread2) // 比较两个线程ID,若不同返回0,否则返回非0值
注意:
(1)这两个函数中的线程ID对象是不透明的,不是轻易能检查的。因为线程ID是不透明的对象,所以C语言的==操作符不能用于比较 两个线程ID。
(2)gettid():是内核给线程(轻量级进程)分配的进程id,全局(所有进程中)唯一;//#include <sys/types.h>
(3)pthread_self():是在用户态实现的,获取的id实际上是主线程分配给子线程的线程描述符的地址而已,只是在当前进程空间中是唯一的。
#include <pthread.h> #include <stdlib.h> #include <stdio.h> #include <sys/syscall.h> #include <sys/types.h> void *fun(void *arg) { pid_t pid; pthread_t tid; pid = getpid(); tid = pthread_self(); printf("%s pid is:%d ;tid is :%d\n", (char*)arg,(unsigned int)pid, (unsigned int)tid, (unsigned int)tid); return 0; } int main() { char *s = "son thread"; pthread_t thread; pthread_create(&thread, NULL, fun, s); printf("in main thread_id is :%d\n",thread); printf("in main pid is:%d ;tid is: %d \n",(unsigned int)getpid(),(unsigned int)pthread_self(),(unsigned int)pthread_self()); sleep(3); return 0; }
2,线程执行顺序
(1)线程的优先级无法保障线程的执行次序。只不过优先级高的线程获取 CPU 资源的概率大一点而已.
(2)setitimer()和signal()。可以精确控制线程的运行时间。
如果没有设置条件,是不能保证线程运行次序的,操作系统会自行随机安排
- POSIX多线程程序设计学习篇之一(线程管理)
- POSIX多线程程序设计学习篇之六(线程属性)
- 《linux程序设计学习笔记》之一---POSIX线程
- POSIX多线程程序设计学习篇之五(线程高级编程)
- POSIX多线程程序设计学习篇之二(互斥量)
- POSIX多线程程序设计学习篇之三(条件变量)
- 学习《POSIX多线程程序设计》笔记一(分离线程)
- POSIX多线程程序设计(第2章:线程)
- POSIX多线程程序设计(第5章:线程高级编程)
- POSIX多线程程序设计(第6章:POSIX针对线程的调整)
- POSIX 多线程程序设计完整入门学习(转载)
- 学习《POSIX多线程程序设计》笔记一
- Posix多线程编程学习笔记(一)—线程基础
- Programming With POSIX Threads(POSIX多线程程序设计)
- POSIX 多线程程序设计
- POSIX 多线程程序设计
- Pthread:POSIX 多线程程序设计
- POSIX 多线程程序设计
- spring cloud
- 测试基础知识
- HDU-3401:Trade(dp+单调队列优化)
- 很厉害的一个数据库连接工具类
- struts2页面下载,从数据库把数据以excel表格形式导出
- POSIX多线程程序设计学习篇之一(线程管理)
- Vitamio 的导入过程
- Hibernate和Mybatis对比(优缺点)
- linux 下卸载PHP
- C语言之指针篇
- 【正一专栏】共享单车那些事儿
- Linux 进程管理
- 不忘初心,继续前行
- 八大排序算法