线程的控制(创建、等待、终止)、分离线程

一、线程控制


1、线程:线程是资源调度的基本单位,线程是进程内部的一个执行流,在进程的地址空间内运行。在Linux 下没有真正意义上的线程,线程是用进程模拟的,又被称为轻量级进程。

        2、由于同⼀一进程的多个线程共享同⼀一地址空间。因此Text Segment、Data Segment都是共享的,除此之外,各线程还共享以下进程资源和环境:

1). ⽂文件描述符表;

2). 每种信号的处理⽅方式(SIG_IGN、SIG_DFL或者⾃自定义的信号处理函数);

3). 当前⼯工作⽬目录;

4). ⽤用户id和组id;

但有些资源是每个线程各有一份的:

1).线程id

2). 上下⽂文,包括各种寄存器的值、程序计数器和栈指针

3). 栈空间

4). errno变量

5). 信号屏蔽字

6). 调度优先级


3、线程创建:

      函数原型:int pthread_create(pthread_t thread, const pthread_attr_t *attr, void (start_routine) (void ), void *arg); 

创建成功:返回0 ;创建失败:返回错误码,可将错误码通过strerror()转换为字符串描述。 

参数1:线程id地址(只在用户区有效)。 

参数2:线程属性,一般设置为NULL。 

参数3:函数指针,指向线程函数。 

参数4:线程函数的参数。


      

创建结果: 

                 


3、终⽌止线程

      如果需要只终⽌止某个线程⽽而不终⽌止整个进程,可以有三种⽅方法:

       1. 从线程函数return。这种⽅方法对主线程不适⽤用,从main函数return相当于调⽤用exit。

       2. ⼀一个线程可以调⽤用pthread_cancel终⽌止同⼀一进程中的另⼀一个线程⽤用pthread_cancel终⽌止⼀一个线程分同步和异步两种情况

       3. 线程可以调⽤用pthread_exit终⽌止⾃自⼰己。

4、线程等待

    返回值:成功返回0,失败返回错误号
    调⽤用该函数的线程将挂起等待,直到id为thread的线程终⽌止。thread线程以不同的⽅方法终⽌止,通过pthread_join得到的终⽌止状态是不同的,总结如下:
    1. 如果thread线程通过return返回,value_ptr所指向的单元⾥里存放的是thread线程函数的返回值。
    2. 如果thread线程被别的线程调⽤用pthread_cancel异常终掉,value_ptr所指向的单元⾥里存放的是常数PTHREAD_CANCELED。
    3. 如果thread线程是⾃自⼰己调⽤用pthread_exit终⽌止的,value_ptr所指向的单元存放的是传给pthread_exit的参数。 如果对thread线程的终⽌止状态不感兴趣,可以      传NULL给value_ptr参数

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>


void* thread1(void* arg)
{


    printf("new thread1\n");
    return (void*)123;
}
void* thread2(void* arg)
{
    while(1)
    {
        printf("new thread2\n");
        sleep(1);
        pthread_exit((void*)456);
    }
    
}
void* thread3(void* arg)//被其他线程cancel
{
    while(1)
    {
        printf("new thread3\n");
        sleep(1);
    }
    return NULL;
}


int main()
{
    pthread_t tid1,tid2,tid3,tid4;
    void* val = NULL;
    pthread_create(&tid1,NULL,thread1,NULL);
    pthread_create(&tid2,NULL,thread2,NULL);
    pthread_create(&tid3,NULL,thread3,NULL);
    pthread_create(&tid4,NULL,thread4,NULL);
    
    pthread_join(tid1,&val);
    printf("thread1 is quit,thread1 id is %lu, exit code:%d\n",tid1,(int)val);
    pthread_join(tid2,&val);
    printf("thread2 is quit,thread2 id is %lu, exit code:%d\n",tid2,(int)val);


    pthread_cancel(tid3);
    pthread_join(tid3,&val);
    printf("thread3 is quit,thread3 id is %lu, exit code:%d\n",tid3,(int)val);


    return 0;


运行结果:



注:

可见在Linux的pthread库中常数PTHREAD_CANCELED的值是-1。可以在头⽂文件pthread.h中找到它的定义。

一般情况下,线程终⽌止后,其终⽌止状态⼀一直保留到其它线程调⽤用pthread_join获取它的状态为止。 但是线程也可以被置为detach 状态,这样的线程⼀一旦终止就⽴立刻回收它占⽤用的所有资源,⽽而不保留终⽌止状态。不能对⼀一个已经处于detach状态的线程调⽤用pthread_join,这样的调⽤用将返回EINVAL。 对⼀一个尚未detach的线程调⽤用pthread_join或pthread_detach都可以把该线程置为detach状态,也 就是说,不能对同⼀一线程调⽤用两次pthread_join,或者如果已经对⼀一个线程调用 了pthread_detach就不能再调⽤用pthread_join了



二、分离线程


在任何⼀一个时间点上,线程是可结合的(joinable)或者是分离的(detached)。一个可结合的线程能够被其他线程收回其资源和杀死。在被其他线程回收之前,

它的存储器资源(例如栈)是不释放的。相反,⼀一个分离的线程是不能被其他线程回收或杀死的,它的存储器 资源在它终⽌止时由系统⾃自动释放。


1、默认情况下,线程被创建成可结合的。为了避免存储器泄漏,每个可结合线程都应该要么被显⽰示地回收,即调⽤用pthread_join;要么通过调⽤用pthread_detach

函数被分离。如果⼀一个可结合线程结束运⾏行但没有被join,则它的状态类似于进程中的Zombie Process,即还有⼀一部分资源没有被回收,所以创建线程者应该调

pthread_join来等待线程运⾏行结束,并可得到线程的退出代码,回收其资源。

2、 由于调⽤用pthread_join后,如果该线程没有运⾏行结束,调⽤用者会被阻塞,在有些情况下我们并不希望如此。例如,在Web服务器中当主线程为每个新来的连接

请求创建⼀一个⼦子线程进⾏行处理的时候,主线程并不希望因为调⽤用pthread_join⽽而阻塞(因为还要继续处理之后到来的连接请求),这时可以在⼦子线程中加入

代码 pthread_detach(pthread_self())

或者⽗父线程调⽤用pthread_detach(thread_id)(⾮非阻塞,可⽴立即返回)

这将该⼦子线程的状态设置为分离的(detached),如此一来,该线程运⾏行结束后会⾃自动释放所有资源。


#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>


void* thread(void *_arg)
{
    //pthread_detach(pthread_self());//线程自已设置自已的可分离属性
printf("new thread is run...\n");
    return (void*)1;
}


int main()
{
    pthread_t tid;
    int ret = pthread_create(&tid,NULL,thread,NULL);
    if(ret != 0)
    {
        printf("thread create failed,error code:%s\n",strerror(ret));
return ret;
    }
    sleep(1);
    pthread_detach(tid);//将子线程属性设置为分离(非阻塞,可立即返回)
    void* val = NULL;
    if((pthread_join(tid, &val) != 0))
    {
        printf("thread wait failed\n");
ret = 1;
}
    else
    {
        printf("thread id : %u ,exit code : %d\n",tid, (int)val);
ret = 0; 
    }
    return ret;
}


运行结果:



                                                                   




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459443.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从netty-example分析Netty组件

分析netty从源码开始 准备工作&#xff1a; 1.下载源代码&#xff1a;https://github.com/netty/netty.git 我下载的版本为4.1 2. eclipse导入maven工程。 netty提供了一个netty-example工程&#xff0c; 分类如下&#xff1a; Fundamental Echo ‐ the very basic client and …

cep

cep posted on 2015-12-16 17:03 秦瑞It行程实录 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/ruiy/p/5051673.html

RHCS集群原理概述

一、 什么是RHCSRHCS是Red Hat Cluster Suite的缩写&#xff0c;也就是红帽集群套件&#xff0c;RHCS是一个能够提供高可用性、高可靠性、负载均衡、存储共享且经济廉价的集群工具集合&#xff0c;它将集群系统中三大集群架构融合一体&#xff0c;可以给web应用、数据库应用等提…

Linux学习笔记11——文件I/O之二

一、文件共享 内核使用三种数据结构表示打开的文件&#xff0c;它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。 1、每个进程在进程表中都有一个记录项&#xff0c;记录项中包含有一张打开文件描述表  2、内核为所有打开文件维持一张文件表  3、每…

Git Proxy开关

2019独角兽企业重金招聘Python工程师标准>>> 这个是配合ShadowSocks使用的&#xff0c;在~/.bash_aliases或者~/.bash_profile中设置以下代码&#xff1a; #git proxy enable alias gitpe"git config --global http.proxy socks5://127.0.0.1:1080;git config …

平衡二叉查找树插入节点操作( AVLTree ):旋转、调整平衡

AVL树的插入 在向一棵本来高度平衡的AVL树中插入一个新节点时&#xff0c;如果树中某个结点的平衡因子的绝对值 > 1&#xff0c;则出现了不平衡。设新插入结点为P&#xff0c;从结点P到根节点的路径上&#xff0c;每个结点为根的子树的高度都可能增加1&#xff0c;因此在每…

Fork/Join框架介绍

转http://www.infoq.com/cn/articles/fork-join-introduction/ 1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架&#xff0c; 是一个把大任务分割成若干个小任务&#xff0c;最终汇总每个小任务结果后得到大任务结果的框架。 我们再通过Fork和…

为什么析构函数可以能声明为虚函数,构造函数不可以

转自&#xff1a;http://blog.csdn.NET/chen825919148/article/details/8020550 构造函数不能声明为虚函数&#xff0c;析构函数可以声明为虚函数&#xff0c;而且有时是必须声明为虚函数。 不建议在构造函数和析构函数里面调用虚函数。 构造函数不能声明为虚函数的原因是: 1 …

信号集操作函数,信号未决、阻塞、递达

转载&#xff1a;信号集操作函数&#xff0c;信号阻塞与未决 一&#xff0c;信号集及相关操作函数 信号集被定义为一种数据类型&#xff1a; typedef struct { unsigned long sig[_NSIG_WORDS]&#xff1b; } sigset_t 信号集用来描述信号的集合&#xff0c;每个信号占用一位&a…

线程安全和可重入函数的联系与区别

1、 线程安全&#xff1a; 线程安全是多线程访问时&#xff0c;采用了加锁机制&#xff0c;当一个线程访问该类的某个数据时&#xff0c;进行保护&#xff0c;其他线程不能进行访问直到该线程访问完&#xff0c;其他线程才可以使用。不会出现数据不一致或数据污染。 线程不…

C++11 多线程 基础

C11开始支持多线程编程&#xff0c;之前多线程编程都需要系统的支持&#xff0c;在不同的系统下创建线程需要不同的API如pthread_create()&#xff0c;Createthread()&#xff0c;beginthread()等&#xff0c;使用起来都比较复杂&#xff0c;C11提供了新头文件<thread>、…

LB负载均衡集群--LVS

LB集群&#xff1a;LB集群是load balance 集群的简写&#xff0c;翻译成中文就是负载均衡集群。常用的负载均衡开源软件有nginx、lvs、keepalived &#xff0c;商业的硬件负载设备F5、Netscale。LB集群架构&#xff1a;当用户的请求过来时&#xff0c;会直接发到分发器&#xf…

2015 UESTC 搜索专题B题 邱老师降临小行星 记忆化搜索

邱老师降临小行星 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/61Description 人赢邱老师和任何男生比&#xff0c;都是不虚的。有一天&#xff0c;邱老师带妹子(们)来到了一个N行M列平面的小行星。对于每一个着陆地点&#xf…

优化表的数据类型

我们可以使用PROCEDURE ANALYSE()对当前已有应用的表类型的判断&#xff0c;该函数可以对数据表中的列的数据类型提出优化建议&#xff0c;可以根据应用的实际情况酌情考虑是否实施优化。语法&#xff1a; SELECT * FROM tbl_name PROCEDURE ANALYSE(); SELECT * FROM tb…

Linux 信号之mysleep

一、 用alarm和pause实现sleep(3)函数,称为mysleep。 1. main函数调用mysleep函数,后者调用sigaction注册了SIGALRM信号的处理函数sig_alrm。 2. 调用alarm(seconds)设定闹钟。 3. 调用pause等待,内核切换到别的进程运行。 4. seconds秒之后,闹钟超时,内核发SIGALRM给这个…

JAVA 操作系统已经来到第五个版本了 现陆续放出三个版本 这是第二个版本

1 package System2;2 3 import javax.swing.*;4 5 import java.awt.*;6 import java.awt.event.ActionEvent;7 import java.awt.event.ActionListener;8 import java.awt.event.KeyListener;9 import java.util.*;10 /**11 * 作者:范铭祥12 * 内容及功能&#xff1a; 显示框…

标准Web系统的架构分层

1、架构体系分层图 在上图中我们描述了Web系统架构中的组成部分。并且给出了每一层常用的技术组件/服务实现。需要注意以下几点&#xff1a; 系统架构是灵活的&#xff0c;根据需求的不同&#xff0c;不一定每一层的技术都需要使用。例如&#xff1a;一些简单的CRM系统可能在产…

数据链路层差错检测:CRC(循环冗余检验)

1、循环冗余检验&#xff08;CRC&#xff09;&#xff1a; 在发送端&#xff0c;先把数据划分为祖&#xff0c;假定每组K个比特。现假定待传送的数据M 101001&#xff08;k6&#xff09;。CRC运算就是在数据M后面添加提供差错检测的n位冗余码&#xff0c;然后构成一个帧发送出…

算法导论笔记:25所有节点对的最短路径问题

本章考虑在给定的有向加权图G(V, E)&#xff0c;对于所有的节点u,v∈V&#xff0c;找到一条从节点u到节点v的最短路径。希望以表格的形式表示输出&#xff1a;第u行第v列给出的是节点u到节点v的最短路径权重。 对于这个问题&#xff0c;如果是运行|V|次单源最短路径算法来解决所…

iOS开发~UI布局(二)storyboard中autolayout和size class的使用详解

一、概要&#xff1a;前一篇初步的描述了size class的概念&#xff0c;那么实际中如何使用呢&#xff0c;下面两个问题是我们一定会遇到的&#xff1a;1、Xcode6中增加了size class&#xff0c;在storyboard中如何使用&#xff1f; 2、auto layout该如何与size class配合来进行…