当前位置: 首页 > news >正文

安顺网站建设上海建设银行官网

安顺网站建设,上海建设银行官网,腾讯企业邮箱怎么注册,北京 网站建设60011. 线程 1. 线程概述1.1 线程概念1.1.1 什么是线程1.1.2 线程是如何创建起来的1.1.3 线程的特点1.1.4 线程与进程 1.2 并发和并行 2. 线程 ID3. 创建线程4. 终止线程5. 回收线程6. 取消线程6.1 取消一个线程6.2 取消状态以及类型6.3 取消点6.4 线程可取消性的检测 7. 分离线程… 11. 线程 1. 线程概述1.1 线程概念1.1.1 什么是线程1.1.2 线程是如何创建起来的1.1.3 线程的特点1.1.4 线程与进程 1.2 并发和并行 2. 线程 ID3. 创建线程4. 终止线程5. 回收线程6. 取消线程6.1 取消一个线程6.2 取消状态以及类型6.3 取消点6.4 线程可取消性的检测 7. 分离线程8. 注册线程清理处理函数9. 线程属性9.1 线程栈属性9.2 分离状态属性 10. 线程与信号10.1 信号如何映射到线程10.2 线程的信号掩码10.3 向线程发送信号10.4 异步信号安全函数 1. 线程概述 1.1 线程概念 1.1.1 什么是线程 线程是参与系统调度的最小单位它被包含在进程之中是进程中的实际运行单位。一个线程指的是进程中的一个单一顺序的控制流或者说是执行流一个进程中可以创建多个线程多个线程实现并发运行每个线程执行不同的任务。 1.1.2 线程是如何创建起来的 当一个程序启动时就有一个进程被操作系统创建与此同时一个线程也立刻运行该线程通常叫做程序的主线程因为它是程序一开始就运行的线程。应用程序通常是以 main() 作为入口开始运行的所以 main() 就是主线程的入口函数。任何一个进程都包含一个主线程只有主线程的进程称为单线程进程多线程的其它线程通常是由主线程调用 pthread_create 创建的。主线程通常会在最后结束运行执行各种清理工作。 1.1.3 线程的特点 线程是程序最基本的运行单位真正运行的是进程中的线程。当启动应用程序后系统就创建了一个进程可以认为进程仅仅是一个容器它包含了线程运行所需的数据结构、环境变量等信息。同一进程中的多个线程将共享该进程中的全部系统资源但同一进程中的多个线程有各自的调用栈自己的寄存器环境、自己的线程本地存储。 线程的特点如下 线程不单独存在而是包含在进程中线程是参与系统调度的基本单位可并发执行。共享进程资源 1.1.4 线程与进程 进程也可以创建多个进程来并发执行但是进程间切换开销大而且进程间通信较为麻烦。线程创建的速度远大于进程创建的速度多线程在多核处理器上更有优势。 1.2 并发和并行 串行是指必须完成上一个任务才能去做下一个任务 并行是指多个任务可以同时执行 并发强调的是时分复用是指可以打断当前执行的任务而去执行另一个任务 2. 线程 ID 进程 ID 在整个系统中都是唯一的但线程 ID 只有在它所属的进程上下文中才有意义。 #include pthread.h pthread_t pthread_self(); // 获取自己的线程 ID int pthread_equal(pthread_t t1,pthread_t t2); // 检查两个线程 ID 是否相等相等返回非0否则返回03. 创建线程 #include pthread.h int pthread_create(pthread_t *thread,const pthread_attr_t *attr, void*(*start_routine)(void*),void*arg); /** thread:函数成功返回时新创建的线程 ID 会保存在thread指向的内存中* attr:指向一块缓冲区该缓冲区定义里线程的各种属性如果是NULL表示以默认属性* start_routine:函数指针指向一个函数新创建的线程从该函数开始运行。返回值和参数都为void*参数就是第四个参数arg* arg:传递给函数的参数。一般情况下需要将arg指向一个全局或堆变量也就是说在线程的生命周期内该参数必须存在。也可以设置为NULL表示不需要传参。*/static void *routine(void *arg) {cout 新线程创建成功进程 ID: getpid() 线程 ID: pthread_self()endl;return (void*)0; } int main() {pthread_t tid;pthread_create(tid,NULL,routine,NULL);cout 我是主线程进程ID: getpid() 线程 ID: pthread_self()endl;sleep(1);return 0; }休眠 1 秒是因为如果主线程不进行休眠它就可能立马退出新线程可能就没有机会运行 运行之后可以发现两个线程的进程 ID 都是一样的但是线程 ID 不同 4. 终止线程 在线程的执行函数中调用 return 返回返回值就是线程的退出码线程调用 pthread_exit()调用 pthread_cancel() 取消线程 在进程的任意位置调用 exit() 或 _exit() 都会导致进程终止 #include pthread.h void pthread_exit(void *retval);线程退出码可由另一个线程调用 pthread_join() 获取。但是要注意retval 不能分配在线程栈中因为不能保证该空间是否有效。 5. 回收线程 #include pthread.h int pthread_join(pthread_t thread,void **retval); /* * thread:需要等待的线程* retval:如果不为NULL将线程的退出状态保存在*retval中。如果目标线程被取消将PTHREAD_CANCELED保存。如果对退出状态不关系可以设置为NULL*/该函数会阻塞式等待指定的线程终止。如果该线程已经终止则立即返回。如果多个线程同时调用那么结果是不确定的。 若线程未分离(detached)则必须使用该函数来等待线程终止回收线程资源如果线程终止后没有其他线程调用该函数回收该线程那么该线程将变成僵尸线程。如果僵尸进程过多会导致系统无法创建新的线程但是进程终止后进程会被其父进程回收所以僵尸进程同样也会被回收。 pthread_join() 和 waitpid() 的区别在于 线程之间的关系是对等的。进程中的任意线程均可调用 pthread_join() 来等待另一个线程终止。但是父进程如果使用 fork() 创建了子进程那么它也是唯一能够对子进程调用 wait() 的进程不能以非阻塞方式调用 pthread_join()但是 waitpid() 可以实现非阻塞方式等待也可以是阻塞式等待。 6. 取消线程 向一个线程发送一个信号要求它立刻退出就叫做取消线程。 6.1 取消一个线程 #include pthread.h int pthread_cancel(pthread_t thread);发出取消请求后函数立即返回不会等待目标线程的退出。默认情况下目标线程也会立即退出。但是线程可以设置自己不被取消或者控制如何被取消所以该函数并不会等待线程终止仅仅是提出请求。 6.2 取消状态以及类型 #include pthread.h int pthread_setcancelstate(int state, int *oldstate); int pthread_setcanceltype(int type, int *oldtype); // 如果对线程取消之前的状态及类型不感兴趣可以将第二个参数设置为NULL /* state:* PTHREAD_CANCEL_ENABLE:线程可以取消也是新创建线程取消状态的默认值* PTHREAD_CANCEL_DISABLE:线程不可以被取消接收到取消请求后会将请求挂起直到取消状态改变* / /* type:* PTHREAD_CANCEL_DEFERRED:取消请求到来时线程还是继续运行取消请求被挂起直到线程到达某个取消点这也是默认类型* PTHREAD_CANCEL_ASYNCHRONOUS:可能会在任何时间点取消线程一般不用。如果线程的取消状态是默认的那么对取消请求的操作取决于取决类型。当某个线程调用 fork() 创建子进程之后子进程会继承调用线程的取消状态和取消类型而当某线程调用 exec 函数时会将新程序主线程的取消状态和类型设为默认值。 6.3 取消点 将线程的取消类型设置为默认时收到其它线程发送来的取消请求时仅当线程抵达某个取消点时取消请求才会起作用。 取消点就是一些列函数当执行到这些函数时才会真正相应取消请求。在没有出现取消点时取消请求是无法得到处理的因为此时正在执行的代码不能被停止。 取消点可以使用man 7 pthreads查看 6.4 线程可取消性的检测 如果正在执行的是一个不含取消点的循环可以使用 pthread_testcancel() 产生一个取消点如果已有处于挂起状态的取消请求那么只要调用该函数线程就会终止。 #include pthread.h void pthread_testcancel();7. 分离线程 有时不关心线程的返回状态只希望系统在线程终止时能够自动回收线程资源并将其移除。 #include pthread.h int pthread_detach(pthread_t thread);一个线程可以将别的线程分离也可以分离自己。一个线程一旦处于分离状态就不能使用 pthread_join() 来获取终止状态当其终止后会自动回收线程资源。 8. 注册线程清理处理函数 与进程不同一个线程可以注册多个清理函数这些清理函数记录在栈中每个线程都可以拥有一个清理函数栈栈是一种先进后出的数据结构。 #include pthread.h void pthread_cleanup_push(void (*routine)(void*), void *arg); void pthread_cleanup_pop(int execute);当线程执行以下动作时清理函数栈中的函数才会被执行 线程调用 pthread_exit() 退出时线程响应取消请求时用非 0 参数调用 pthread_cleanup_pop() 除了以上三种情况之外其他方式终止线程将不会执行线程清理函数。 execute 如果是 0清理函数不会被调用只是将清理函数栈中最顶层的函数移除如果非 0会将函数执行并清理。 在使用时必须在与线程相同的作用域中以匹配对的形式使用。 有时线程清理函数并不一定需要在线程退出时才执行可以调用 pthread_cleanup_pop() 传入非 0手动执行清理函数。 9. 线程属性 创建线程时可以设置属性当定义 pthread_attr_t 对象之后需要使用 pthread_attr_init() 和 pthread_attr_destroy() 执行初始化和销毁工作。 #include pthread.h int pthread_attr_init(pthread_attr_t *attr); int pthread_attr_destroy(pthread_attr_t *attr);该结构体中的属性比较多这里不详细介绍。Linux 为该结构体对象的每种属性提供了设置属性的接口以及获取属性的接口。 9.1 线程栈属性 #include pthread.h int pthread_attr_setstack(pthread_attr_t *attr,void *stackaddr,size_t stacksize); int pthread_attr_getstack(const pthread_attr_t *attr, void **stackaddr,size_t *stacksize);// 单独设置或获取大小地址等信息 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize); int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr); int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr);9.2 分离状态属性 #include pthread.h int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate); /* detachstate:* PTHREAD_CREATE_DETACHED:新建线程一开始就处于分离状态无法被其他线程回收* PTHREAD_CREATE_JOINABLE:正常启动线程可以被其他线程回收10. 线程与信号 10.1 信号如何映射到线程 信号在一些方面是属于进程层面由进程中的所有线程共享的而在另一些方面是属于单个线程层面的。 信号的系统默认行为是属于进程层面的。当进程中任一线程收到任何一个未经处理忽略或捕捉的信号时会执行该信号的默认操作通常是停止或终止进程。信号处理函数属于进程层面进程中的所有线程共享程序中所注册的信号处理函数信号的发送既可以针对整个进程也可以针对某个特定的线程符合以下任意一个时是针对某个线程 产生了硬件异常相关信号如 SIGBUS、SIGFPE、SIGILL 和 SIGSEGV 信号。这些硬件异常信号在某个线程执行指令的过程中产生也就是说这些信号是由某些线程引起的那么在这种情况下系统会将信号发送给该线程当线程试图对已断开的管道进行写操作时所产生的 SIGPIPE 信号由函数 pthread_kill() 或 pthread_sigqueue() 所发出的信号这些函数运行线程向同一进程下的其他线程发送指定的信号。 当一个多线程进程接收到一个信号时且该信号绑定了信号处理函数时内核会任选一个线程来接收这个信号让进程对单个信号重复接收没有意义信号掩码其实是属于线程层面的对于一个多线程来说各个线程可以调用 pthread_sigmask() 来设置它们各自的信号掩码。针对整个进程所挂起的信号以及针对每个线程所挂起的信号内核都会分别进行维护。 10.2 线程的信号掩码 #include signal.h int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);每个刚创建的线程都会从创建者处继承信号掩码这个新的线程可以通过该函数改变它的信号掩码 10.3 向线程发送信号 #include signal.h int pthread_kill(pthread_t thread, int sig);10.4 异步信号安全函数 应用程序中涉及信号处理函数时必须要非常小心因为信号处理函数可能会在程序执行的任意时间点被调用从而打断主程序。 前面介绍了线程安全函数可以被多个线程同时调用每次都能得到预期的结果但是这里有前提条件那就是不能在信号处理函数中调用。 异步信号安全函数async-signal-safe function指的是可以在信号处理函数中被安全调用的线程安全函数。可以使用 man 7 signal查看。 对于一个安全的信号处理函数需要做到以下几点 首先确保信号处理函数本身的代码是可重入的且只能调用异步信号安全函数当主程序执行不安全函数或是去操作信号处理函数也可能会更新的全局数据结构时要阻塞信号的传递。
http://www.pierceye.com/news/388257/

相关文章:

  • 自己做网站费用html5结构的网站
  • wordpress做资源分享站做网站的图哪来
  • 国外设计欣赏网站线上建模培训班哪个好
  • 微信网站建设合同怎么在本地搭建网站
  • 班级网站怎么做网页制作临沂网站制作方案
  • 泰州网站建设服务好wordpress调用分类名
  • 中英切换的网站咋做怎样在网站做推广
  • 初学网站开发书籍如何提升网站打开速度
  • 深圳微信网站建设公司哪家好网站 维护 页面
  • 做个企业网站需要多少钱北京西站到大兴机场
  • 数字博物馆网站建设动态设计是什么意思
  • 沧州市做网站价格wordpress构建自己的网站
  • seo外链网站源码新公司注册核名
  • 游戏网站建设的策划方案python做电子商务网站
  • pxhere素材网站网上搞钱的野路子
  • 有没有帮人做数学题的网站9377游戏盒子
  • 微信网站建设报价网站优化提升排名
  • wap网站分享代码自定义网站建设
  • 网站换域名了怎么办seo百度帐号注册
  • 淄博网站建设公司羊肉片机网站模板制作
  • 邯郸网站设计价位南京h5 网站建设
  • wordpress主要函数seo是哪个英文的缩写
  • 自助建站网站seo公司静态网站作品
  • 内部网站建设、北京的网页建设公司
  • 网站建设的后台登录oa信息管理系统
  • 镇江企业网站建设公司wordpress模板如何修改
  • 汕头中文建站模板建设全网营销型网站
  • 外贸网站建设盲区雄安移动网络电视
  • 建站方法友情链接发布平台
  • 做美剧盗版网站国内购物网站案例分析