linux shell 多线程中回车不退出当前线程

Linux线程退出方式总结 - CSDN博客
Linux线程退出方式总结
在编写多线程代码时,经常面临线程安全退出的问题。
一般情况下,选择检查标志位的方式:
在线程的while循环中,执行完例程后,都对标志位进行检查,如果标志位指示继续执行则再次执行例程,如果标志位设置为退出状态,则跳出循环,结束线程的运行。
这个标志位需要主线程(或其他线程)设置,设置后,主线程调用pthread_join接口进入休眠(接口参数指定了等待的线程控制指针),子线程退出后,主线程会接收到系统的信号,从休眠中恢复,这个时候就可以去做相关的资源清除动作。
这个方法可以保证子线程完全退出,主线程再去做相关的资源清除操作
时序图如下
但是某些应用中,或许会发生下面情况:
子线程阻塞在某个操作无法被唤醒,即使主线程设置了标志位,由于子线程进入了休眠无法醒过来,也没有办法去检查标志位,这个时候调用pthread_join进入休眠的主线程等待不到子线程退出的信号,也会一直休眠,系统进入死锁。
为了更安全地使线程退出,主线程通过pthread_cancel函数来请求取消同一进程中的其他线程,再调用pthread_join等待指定线程退出。使用pthread_cancel接口,需要了解Linux下线程的两个属性,可取消状态和可取消类型,以及取消点的概念。
可取消状态:包括PTHREAD_CANCEL_ENABLE和PTHREAD_CANCEL_DISABLE。当线程处于PTHREAD_CANCEL_ENABLE,收到cancel请求会使该线程退出运行;反之,若处于PTHREAD_CANCEL_DISABLE,收到的cancel请求将处于未决状态,线程不会退出。线程启动时的默认可取消状态为PTHREAD_CANCEL_ENABLE,可以通过接口pthread_setcancelstate改变可取消状态的属性。
可取消类型:包括PTHREAD_CANCEL_DEFERRED和PTHREAD_CANCEL_ASYNCHRONOUS。当处于PTHREAD_CANCEL_DEFERRED,线程在收到cancel请求后,需要运行到取消点才能退出运行;如果处于PTHREAD_CANCEL_ASYNCHRONOUS,可以在任意时间取消,只要收到cancel请求即可马上退出。线程启动时默认可取消类型为PTHREAD_CANCEL_DEFERRED,可通过pthread_setcanceltype修改可取消类型。
取消点:线程检查是否被取消并按照请求进行动作的一个位置。
采用PTHREAD_CANCEL_DEFERRED取消方式是因为线程可能在获取临界资源后(如获取锁),未释放资源前收到退出信号,如果使用PTHREAD_CANCEL_ ASYNCHRONOUS的方式,无论线程运行到哪个位置,都会马上退出,而占有的资源却得不到释放。
采用PTHREAD_CANCEL_DEFERRED取消方式,线程需要运行到取消点才退出,而主线程在调用pthread_cancel后,不能马上进行线程资源释放,必须调用pthread_join进入休眠,直至等待指定线程退出。
使用PTHREAD_CANCEL_DEFERRED方式并不能完全避免这个问题,因为无法保证在获取临界资源后(比如lock操作)不会进行可以作为取消点的操作(如进行sleep),此时主线程如果对该线程发送cancel信号,线程将会在不释放锁的情况下直接结束运行,即还是会出现在释放资源前线程就退出的问题。
为了避免上述情况,不仅需要设置可取消类型,还需要设置可取消状态。将获取临界资源-释放临界资源之间的代码块都设置成PTHREAD_CANCEL_DISABLE状态,其余的代码块都设置成PTHREAD_CANCEL_ENABLE状态,确保线程在安全的地方退出。如果在可以安全退出的代码块不存在取消点系统调用,可以调用pthread_testcancel函数自己添加取消点。
伪代码描述如下:
void* subThread(void*)
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&oldCancleState);
pthread_testcancel();
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,&oldCancleState);
void* mainThread(void*)
pthread_cancel(subThread);
pthread_join(subThread,null);
无论使用哪种方式,核心点就是要保证线程退出的时候不会获取了某些临界资源而无法释放
POSIX.1定义的取消点见下:
注意:当主线程调用pthread_cancel接口后,只是将取消请求发送给指定线程,
对接口的成功调用不能保证指定线程已经退出,需要调用pthread_join等待指定线程完全退出,再进行相关资源的释放。
本文已收录于以下专栏:
相关文章推荐
1.线程相关的概念:
程序:二进制程序放置在存储媒介中(硬盘,光盘,软盘等)以物理文件形式存在。
进程:程序被触发后,执行者的权限与属性,程序的程序代码与所需数据等都会被加载到内存中,操作系统...
在前文讨论了线程创建的一些基本东西,这里讨论有哪些方法可以使线程终止,线程终止又是如何与创建所需的参数进行关联的。
一,正常终止
    线程在执行完成之后,正常终止。
二,线程取消
linux下用C开发多线程程序,Linux系统下的多线程遵循POSIX线程接口,称为pthread。
int pthread_create(pthrea...
pthread_cancel函数发送终止信号
pthread_setcancelstate函数设置终止方式
pthread_testcancel函数取消线程(另一功能是:设置...
关键字: linux 查进程、杀进程、起进程
    ps命令查找与进程相关的PID号:
    ps a 显示现行终端机下的所有程序,包括其他用户的程序。
    ps -A 显...
多线程退出有三种方式:
(1)执行完成后隐式退出;
(2)由线程本身显示调用pthread_exit 函数退出;
    pthread_exit (void * retval) ; 
学习环境 :  Centos6.5
Linux 内核 2.6
Linux线程部分总结分为两部分:(1)线程的使用 ,(2)线程的同步与互斥。
第一部分线程的使用主要介绍,线程的概念,创建线程...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
白手起家, 积分 10, 距离下一级还需 190 积分
论坛徽章:0
11 int a = 10;
12 void *my1(void)
14& &&&printf(&i am one thread!\n&);
15& &&&sleep(3);& && && && && && && && && && && &
& && && && && && && && && && && &
16& &&&printf(&thread leave!\n&);
17& &&&printf(&The number of a:%d\n&, a);
20 int main(void)
22& &&&pthread_t id1;
23& &&&pthread_create(&id1, NULL, (void *)my1,
24& &&&printf(&back to the main funciton!\n&);
25& &&&printf(&i am the main!\n&);
26& &&&return 0;
按照这里打印的结果看,好像线程也退出了。按照理论,
线程使用的是进程的资源,进程退出了,那么线程自然也
退出了,到底是他们两个哪个先退出呢?线程睡眠了,然
后进程执行完了,线程不会醒来了???因为资源被回收
了吗???
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp
论坛徽章:1
当然了,寄主都没了,生存空间不在了。线程不能独立存在。
白手起家, 积分 13, 距离下一级还需 187 积分
论坛徽章:0
天都塌了啊,没空气了
论坛徽章:95
& & 皮之不存,毛將焉附。
论坛徽章:1
肯定退出撒。
北京盛拓优讯信息技术有限公司. 版权所有 京ICP备号 北京市公安局海淀分局网监中心备案编号:22
广播电视节目制作经营许可证(京) 字第1234号
中国互联网协会会员&&联系我们:
感谢所有关心和支持过ChinaUnix的朋友们
转载本站内容请注明原作者名及出处Linux如何返回线程退出时的数据(以整数为例) - OlderDriver - 博客园
随笔 - 10, 文章 - 0, 评论 - 16, 引用 - 0
在Linux中,线程的应用还是比较广泛的,同时,线程退出的返回值对线程来说,也是一种比较客观的数据传输。
本文主要是在Linux中进行测试,不涉及windows等其他OS。
1. 线程的创建
& & pthread_create(pthread_t *thread,const pthread_attr_t *attr,void*(*start_routine)(void*),void* arg);
首先,参数一:代表的是线程的pid地址
& & & 参数二:代表的是是否设置线程的分离属性,这里设置为NULL,不分离
& & & 参数三:代表的是线程的处理函数
& & & 参数四:线程处理函数的参数列表,这里设置为NULL,不带参数内容
    &(注意,这里主要是创建线程的作用)
2. 线程的等待
& & pthread_join(pthread_t thread, void **retval)
首先: & 参数一: 代表线程pid
& & & & & 参数二: 代表线程的返回值 (--& 这个是本文讨论的重点参数)
3. 例子设计:
& & 这里设计两个线程,线程一是通过一般的return返回,作为线程的返回值;线程二,则是使用线程库中的pthread_exit()函数
来进行返回参数。
  首先,函数pthread_exit(void *retval)
     & 这里的retval就是线程退出的时候返回给主线程的值,也是今天需要讨论的情况。
  例子如下:
1 #include &pthread.h&
2 #include &stdio.h&
3 #include &string.h&
4 #include &unistd.h&
5 #include &errno.h&
7 #define PTHREAD_NUM
9 void *sendData(void *arg)
<span style="color: # {
<span style="color: #
static int count = <span style="color: #;
<span style="color: #
<span style="color: #
pthread_exit((void*)(&count));
<span style="color: #
<span style="color: # }
<span style="color: #
<span style="color: #
<span style="color: # void *recvData(void *arg)
<span style="color: # {
<span style="color: #
static int count = <span style="color: #;
<span style="color: #
<span style="color: #
return (void *)(&count);
<span style="color: #
<span style="color: #
<span style="color: # }
<span style="color: #
<span style="color: #
<span style="color: # int main(int argc,char *argv[])
<span style="color: # {
<span style="color: #
pthread_t pid[PTHREAD_NUM];
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
if((retPid = pthread_create(&pid[<span style="color: #],NULL,sendData,NULL)) != <span style="color: #)
<span style="color: #
<span style="color: #
perror("create pid first failed");
<span style="color: #
return -<span style="color: #;
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
if((retPid = pthread_create(&pid[<span style="color: #],NULL,recvData,NULL)) != <span style="color: #)
<span style="color: #
<span style="color: #
perror("create pid second failed");
<span style="color: #
return -<span style="color: #;
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
if(pid[<span style="color: #] != <span style="color: #)
<span style="color: #
<span style="color: #
<span style="color: #
pthread_join(pid[<span style="color: #],(void**)&ret);
<span style="color: #
printf("get thread 0 message: %d\n",*ret);
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
if(pid[<span style="color: #] != <span style="color: #)
<span style="color: #
<span style="color: #
pthread_join(pid[<span style="color: #],(void**)&dat);
<span style="color: #
printf("get thread 1 message: %d\n",*dat);
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
return <span style="color: #;
<span style="color: # }
& &讲解:这里的最主要的问题就是我们需要进行强制类型的转换。
  首先,对于pthread_exit这个函数,他的返回参数的类型为void *,现在我们返回的是一个“整数”,因此必须将其进行转换
& & & &1. 先转换为整形指针,count为int类型,那么&count为int*类型,同样为了保持匹配,这里本人使用显式的调用,直接写作为
& & & & &&count,其实这个表明了现在变成了一个int的指针,这个时候与void*匹配的话,需要进行强制转换,也就是代码中的
& & & & &(void*)(&count);
& & & &2. return这个关键字进行返回值得时候,同样也是需要进行强制类型的转换。线程函数的返回类型是void*,那么对于count这个
& & & & &整形数值来说,必须进行转换为void的指针类型(即void*),因此有:(void*)((int*)&count);
& & & &3. 对于接收返回值的线程函数pthread_join来说,有两个作用。其一就是等待线程结束,其二就是获取线程结束的时候返回的数值
& & & & &是什么。所以,对于它的参数类型是void**这种二级指针的,我们可以把它分解为一级指针,这样就比较容易进行理解和调用。本文
& & & & 讨论的是整数,那么设置接收返回值得为一个整形指针,这样就感觉给二级指针void**降阶了。
& & & &4. 对接收返回值得参数进行强制转换,这里定义接收返回值得类型是int*,因此转化为void**,也就是(void**)&ret,因为&ret就已
& & & & &经说明了现在的类型为int**,然后显式地转为void**即可
   5. 另外,本文在返回整数数值的时候使用到了static这个关键字,这是因为必须确定返回值的地址是不变的。对于count变量而言,在
& & & & &内存上来讲,属于在栈区开辟的变量,那么在调用结束的时候,必然是释放内存空间的,相对而言,这时候,就没办法找到count所代表
& & & & &内容的地址空间。这就是为什么很多人在看到swap交换函数的时候,为什么写成swap(int,int)是没有办法进行交换的,所以,如果我
& & & & &们需要修改传过来的参数的话,必须是要使用这个参数的地址,或者是一个变量本身是不变的内存地址空间,这样才可以进行修改,否则,
& & & & &修改失败或者返回值是随机值。
& & 结果:
& & & & & & &&
& & & 上述的结果表明,返回的数值是我们所要求的数值,是正确的。读者可以试着返回的是一个字符串,这样就比返回是一个整数
& & &更加简单明了。说到底,整篇文章也就是强制转换的结果。读者可以更加深入地自己去理解Linux下如何安全退出线程 - CSDN博客
Linux下如何安全退出线程
正确退出线程
最近发现以前工作中写的代码有个比较严重的bug,在这里做一下笔记,并做适当扩展,防止以后出现类似的问题。
问题背景是这样的,有一个管理设备用的进程需要从远端FTP服务器上下载软件包,以执行升级操作。管理进程通过select监听socket文件描述符,有消息到来时就调用对应的消息处理函数处理消息。执行从FTP服务器上下载软件包的操作,就是为了响应软件下载消息。在这种框架下,肯定是不能直接在消息处理函数中执行下载任务的,因为这可能导致管理进程阻塞,无法响应其他消息,因此想到重新启动一个线程来执行下载任务。
功能实现非常简单,收到软件下载消息后,在消息处理函数中启动一个线程执行下载任务,线程创建成功后,消息处理函数返回,继续等待下一条消息,并不会等待下载线程结束。由于看Linux系统编程时囫囵吞枣,导致学艺不精,天真地以为下载线程能不留痕迹的安全退出。实际情况却是,默认创建的线程是非分离态的(joinable),这种情况下,父线程需要调用pthread_join来等待子线程结束,只有当pthread_join返回时,子线程才会真正结束,才会释放占用的系统资源。如果想要线程结束后,立即释放占用的系统资源,需要设置线程为分离线程(detached)。
创建分离线程
有两种方法可以设置线程为分离线程,分别是创建时设置线程属性和调用pthread_detach.下面分别来介绍这两种方法。
设置线程属性
创建线程时,可以通过pthread_create的第二个参数传递线程属性。线程有许多属性可以设置,比如堆栈大小、调度方式等,我们这里只设置分离属性,方法如下:
1.初始化一个线程属性对象。
#include &pthread.h&
int pthread_attr_init(pthread_attr *attr);
2.设置分离属性。
#include &pthread.h&
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
这两个函数一个用于设置状态,一个用于获取。设置状态用的两个标志分别为PTHREAD_CREATE_JOINABLE和PTHREAD_CREATE_DETACHED.后一个用于设置线程为分离线程。设置为分离态后,就不能调用pthread_join来获取线程的退出状态了。
3.创建线程,并把设置好的线程属性对象传递给pthread_create函数。
完整代码如下,代码比较简略,没有进行错误处理,实际写代码最好判断一下调用函数的返回值,以确定函数执行成功:
pthread_t a_
pthread_attr_t thread_
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&pthread_attr, PTHREAD_CREATE_DETACH);
pthread_create(&a_thread, &thread_attr, thread_function, NULL);
pthread_attr_destroy(&pthread_attr);
调用pthread_detach
根据pthread_detach的man手册给出的例子,在子线程启动后,通过如下方式调用:
pthread_detach(pthread_self());
如何创建分离线程的方法,这里就讲完了,希望对各位朋友有用,不会和我一样掉进同一个坑里。多进程编程其实会有类似的问题,也就是僵尸进程的问题,这个主题会在下一篇博客中分析,敬请期待。
本文已收录于以下专栏:
相关文章推荐
多线程退出有三种方式:
(1)执行完成后隐式退出;
(2)由线程本身显示调用pthread_exit 函数退出;
&#160; &#160; pthread_exit (void * retval) ;&#160;
1.线程相关的概念:
程序:二进制程序放置在存储媒介中(硬盘,光盘,软盘等)以物理文件形式存在。
进程:程序被触发后,执行者的权限与属性,程序的程序代码与所需数据等都会被加载到内存中,操作系统...
linux线程与线程安全
0.在linux中创建一个线程
void *thread_function(void *dummyPtr)
一个线程安全的class应当满足:
1)多个线程同时访问时,其表现出正确的行为。
2)无论操作系统如何调度这些线程,无论这些线程的执行顺序如何交织。
3)调用端代码无须额外的同步。
一个线程可以调用pthread_cancel终止同一进程中的另一个线程,但是值得强调的是:同一进程的线程间,pthread_cancel向另一线程发终止信号。系统并不会马上关闭被取消线程,只有在被取消...
我并不假定你会使用Linux的线程,所以在这里就简单的介绍一下。如果你之前有过多线程方面的编程经验,完全可以忽略本文的内容,因为它非常的初级。
首先说明一下,在Linux编写多线程程序需要包含头...
1、进程与线程
进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集。从内核的观点看,进程的目的就是担当分配系统资源(CPU时间、内存等)的基本单位。
线程是进程的一个执行流,是C...
首先大家可以看看这篇文章,这篇文章对进程和线程的关系做了生动的讲解:
/blog/2013/04/processes_and_threads.htm...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)linux下 c中怎么让才能安全关闭线程 - CSDN博客
linux下 c中怎么让才能安全关闭线程
多线程退出有三种方式:
(1)执行完成后隐式退出;
(2)由线程本身显示调用pthread_exit 函数退出;
& & pthread_exit (void * retval) ;&
(3)被其他线程用pthread_cance函数终止:
& & pthread_cance (pthread_t thread) ;&
用event来实现。
在子线程中,在循环内检测event。
while(!e.is_active())
当退出循环体的时候,自然return返回。这样子线程会优雅的结束。
注意:选用非等待的检测函数。
pthread 线程有两种状态,joinable(非分离)状态和detachable(分离)状态,默认为joinable。
  joinable:当线程函数自己返回退出或pthread_exit时都不会释放线程所用资源,包括栈,线程描述符等(有人说有8k多,未经验证)。
  detachable:线程结束时会自动释放资源。
Linux man page said:
When a joinable thread terminates, its memory resources (thread descriptor and stack) are not deallocated until another thread performs pthread_join on it. Therefore, pthread_join must be called& once& for each
joinable thread created to avoid memory leaks.
因此,joinable 线程执行完后不使用pthread_join的话就会造成内存泄漏。
解决办法:
1.// 创建线程前设置 PTHREAD_CREATE_DETACHED 属性
pthread_attr_
pthread_attr_init (&attr);
pthread_attr_setdetachstat(&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread, &attr, &thread_function, NULL);
pthread_attr_destroy (&attr);
2.当线程为joinable时,使用pthread_join来获取线程返回&#20540;,并释放资源。
3.当线程为joinable时,也可在线程中调用 pthread_detach(pthread_self());来分离自己。
本文已收录于以下专栏:
相关文章推荐
linux下用C开发多线程程序,Linux系统下的多线程遵循POSIX线程接口,称为pthread。
int pthread_create(pthrea...
在编写多线程代码时,经常面临线程安全退出的问题。
一般情况下,选择检查标志位的方式:
在线程的while循环中,执行完例程后,都对标志位进行检查,如果标志位指示继续执行则再次执行例程,如果标志位设...
在Linux中,默认情况下是在一个线程被创建后,必须使用此函数对创建的线程进行资源回收,但是可以设置Threads
attributes来设置当一个线程结束时,直接回收此线程所占用的系统资源,详细...
在上一篇文章中对线程进行了简单的概述,它在系统中和编程的应用中,扮演的角色是不言而喻的。学习它、掌握它、吃透它是作为一个程序员的必须作为。在接下来的讲述中,所有线程的操作都是用户级的操作。在LINUX...
多线程退出有三种方式:
(1)执行完成后隐式退出;
(2)由线程本身显示调用pthread_exit 函数退出;
&#160; &#160; pthread_exit (void * retval) ;&#160;
《linux wait与waitpid函数的深入分析》
已有 2050 次阅读
20:01 |个人分类:LINUX系统|关键词:waitpid linux 函数 wait 子进程...
Linux下多线程开发一般是
Linux下的C编程实战(一)
――开发平台搭建
&#160;&#160;&#160; Linux操作系统在服务器领域的应用和普及已经有较长的历史,这源于它的开源特点以及其超越Windows的安全性和稳定性。而...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)}

我要回帖

更多关于 shell 多线程并发 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信