Linux的线程java怎么关闭线程

2767人阅读
linux(38)
其实在Linux中,新建的线程并不是在原先的进程中,而是系统通过一个clone()。该系统调用copy了一个和原先进程完全一样的进程,并在这个进程中执行线程函数。不过这个copy过程和fork不一样。 copy后的进程和原先的进程共享了所有的变量,运行环境。这样,原先进程中的变量变动在copy后的进程中便能体现出来。
pthread_join的应用
pthread_join使一个线程等待另一个线程结束。
代码中如果没有pthread_join会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。
所有线程都有一个线程号,也就是Thread ID。其类型为pthread_t。通过调用()函数可以获得自身的线程号。
一个线程的结束有两种途径,一种是象我们下面的例子一样,函数结束了,调用它的线程也就结束了;另一种方式是通过函数pthread_exit来实现。另外需要说明的是,一个线程不能被多个线程等待,也就是说对一个线程只能调用一次pthread_join,否则只有一个能正确返回,其他的将返回ESRCH 错误。
在Linux中,默认情况下是在一个线程被创建后,必须使用此函数对创建的线程进行资源回收,但是可以设置Threads attributes来设置当一个线程结束时,直接回收此线程所占用的系统资源,详细资料查看Threads attributes。
//signaltest.c
  // 子线程阻塞,等待信号,然后输出字符串
  // 主线程从键盘录入字符,给子线程发信号。
#include&stdio.h&
#include&unistd.h&
#include&signal.h&
#include&pthread.h&
#include&time.h&
pthread_ sigset_
voidmyfunc()
 printf("hello\n");
staticvoid*mythread(void*p)
 while(1){
 sigwait(&set,&signum);
 if(SIGUSR1==signum)
 myfunc();
 if(SIGUSR2==signum)
 printf("Iwillsleep2secondandexit\n");
 sleep(2);
sigemptyset(&set);
sigaddset(&set,SIGUSR1);
sigaddset(&set,SIGUSR2);
sigprocmask(SIG_SETMASK,&set,NULL);
pthread_create(&tid,NULL,mythread,NULL);
printf(":");
scanf("%c",&tmp);
if('a'==tmp)
pthread_kill(tid,SIGUSR1);
elseif('q'==tmp)
pthread_kill(tid,SIGUSR2);
pthread_join(tid,&status);
printf("finish\n");
运行结果:
// 如果输入a,子线程打印"hello",主程序继续等待输入;
// 如果输入q,主程序等待子程序结束。子线程打印"I will sleep 2 second and exit",并延时两秒后结束。主线程随之打印"finish",程序结束。
在前面我们提到,可以通过pthread_join()函数来使主线程阻塞等待其他线程退出,这样主线程可以清理其他线程的环境。但是还有一些线程,更喜欢自己来清理退出的状态,他们也不愿意主线程调用pthread_join来等待他们。我们将这一类线程的属性称为detached。如果我们在调用pthread_create()函数的时候将属性设置为NULL,则表明我们希望所创建的线程采用默认的属性,也就是joinable。如果需要将属性设置为detached,则参考下面的例子:
void*start_run(void*arg)
pthread_tthread_
pthread_attr_
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
pthread_create(&thread_id,&attr,start_run,NULL);
pthread_attr_destroy(&attr);
在线程设置为joinable后,可以调用pthread_detach()使之成为detached。但是相反的操作则不可以。还有,如果线程已经调用pthread_join()后,则再调用pthread_detach()则不会有任何效果。linux线程创建、取消、属性设置
<span type="1" blog_id="1532040" userid='
分享到朋友圈
好的文章,和好友一起分享Linux线程退出方式总结(推荐)
转载 & & 投稿:jingxian
下面小编就为大家带来一篇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_testcancel调用,线程执行到这个调用就会退出
/*还有一种方法,在可以安全退出的代码块,我们将线程的可取消类型设置成PTHREAD_CANCEL_ ASYNCHRONOUS,这样即使没有取消点也可以马上退出*/
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,&oldCancleState);
/*存在获取-释放临界资源操作,如果在lock和unlock之间的运行收到cancel信号,且可取消状态为enable,则锁永远无法被释放*/
void* mainThread(void*)
pthread_cancel(subThread);//给subThread发送退出信号
pthread_join(subThread,null);//进入休眠,直到subThread退出成功
无论使用哪种方式,核心点就是要保证线程退出的时候不会获取了某些临界资源而无法释放
POSIX.1定义的取消点见下:
注意:当主线程调用pthread_cancel接口后,只是将取消请求发送给指定线程,
对接口的成功调用不能保证指定线程已经退出,需要调用pthread_join等待指定线程完全退出,再进行相关资源的释放。
以上就是小编为大家带来的Linux线程退出方式总结(推荐)全部内容了,希望大家多多支持脚本之家~
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
在主线程的末尾,我有一段打印的代码:
我执行了代码之后,有时候可以打印出结果,有时候却不可以打印结果:
那么是否和我想的那样,子线程退出会导致主线程退出?
(这个程序是一个压力测试程序,bug有点多)
详细代码如下:
#include &stdio.h&
#include &unistd.h&
#include &string.h&
#include &assert.h&
#include &sys/param.h&
#include &rpc/types.h&
#include &getopt.h&
#include &strings.h&
#include &time.h&
#include &signal.h&
#include &netinet/in.h&
#include &arpa/inet.h&
#include &stdlib.h&
#include &errno.h&
#include &fcntl.h&
#include &pthread.h&
int request_nums = 1;
int already_request_nums = 0;
int clients_num = 1;
int thread_nums = 1;
int failed = 0;
int success = 0;
int benchtime = 1; // 默认持续发起请求的时间
int timerexpired = 0; // 是否请求到指定的时间(1表示时间到,0表示没到时间)
int start = 0; //开始/关闭标志
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
const int MAX_LINE = 2048;
const int port = 80;
// 请求行的最大长度
const int request_size = 2048;
char request[request_size];
const int url_max_size = 100;
char url[url_max_size];
// 发起请求
void *bench(void *arg);
// 构造请求行
void build_request(const char *url);
ssize_t readline(int fd, char *vptr, size_t maxlen);
// 返回已经建立连接的套接字
int create_socket (const char *host);
// 设置非阻塞
void setnonblocking(int sock);
void timeover(int sig) {
timerexpired = 1;
// 显示错误,并且结束进程
void error_die( const char *sc ) {
perror(sc);
作用:设置文件描述符的状态为非阻塞的
参数1:需要修改状态的文件描述符
void setnonblocking(int sock) {
opts=fcntl(sock, F_GETFL);
if(opts&0) {
error_die("fcntl(sock,GETFL)");
opts = opts | O_NONBLOCK;
if(fcntl(sock, F_SETFL, opts)&0) {
error_die("fcntl(sock,SETFL,opts)");
void *bench(void *arg) {
int sockfd[clients_num];
char buf[1024];
req_len = strlen(request); // 请求行的长度
// 创建套接字
for (int i = 0; i & clients_ ++i) {
sockfd[i] = create_socket(url);
if(sockfd[i] & 0) { // 连接服务器失败,所以算一次请求失败
pthread_mutex_lock(&lock);
pthread_mutex_unlock(&lock);
while(!start) {};
while(1) {
if (timerexpired) { // 时间到了,说明上一次线程在请求连接的过程中可能被打断了,所以不算失败
if (failed & 0) {
pthread_mutex_lock(&lock);
pthread_mutex_unlock(&lock);
// pthread_exit((void*)0);
for (int i = 0; i & clients_ ++i) {
int n = write(sockfd[i], request, req_len);
if(n & 0) { // 没有一次发送完,也算做一次请求失败
pthread_mutex_lock(&lock);
pthread_mutex_unlock(&lock);
int m = read(sockfd[i], buf, 1024);
// printf("%s\n", buf);
memset(buf, '\0', 1024);
if (m & 0) {
pthread_mutex_lock(&lock);
pthread_mutex_unlock(&lock);
for (int i = 0; i & clients_ ++i) {
close(sockfd[i]);
// pthread_exit((void*)0);
// 构造请求头
void build_request(const char *url) {
bzero(request, request_size);
strcpy(request, "GET");
strcat(request, " ");
strcat(request, "/");
strcat(request, " ");
strcat(request, "HTTP/1.1");
strcat(request, "\n");
strcat(request, "host: localhost");
strcat(request, "\n\n");
/*readline函数实现*/
ssize_t readline(int fd, char *vptr, size_t maxlen) {
ssize_t n,
for (n = 1; n & n++) {
if ( (rc = read(fd, &c,1)) == 1) {
if (c == '\n')
/* newline is stored, like fgets() */
} else if (rc == 0) {
return(n - 1);
/* EOF, n - 1 bytes were read */
return(-1);
/* error, errno set by read() */
/* null terminate like fgets() */
return(n);
int create_socket (const char *host) {
/*声明套接字和链接服务器地址*/
struct sockaddr_
/*(1) 创建套接字*/
if((sockfd = socket(AF_INET , SOCK_STREAM , 0)) == -1) {
error_die("socket error");
/*(2) 设置链接服务器地址结构*/
bzero(&servaddr , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port); // 默认为8080端口
if(inet_pton(AF_INET , host , &servaddr.sin_addr) & 0) {
printf("inet_pton error for %s\n", host);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd & 0) {
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) & 0) {
perror("连接服务器失败");
return -1;
int main(int argc, char **argv) {
pthread_attr_
// 解析命令行
while((ch = getopt(argc, argv, "n:c:p:u:")) != -1) {
switch(ch) {
case 'n': // 总的请求数
request_nums = atoi(optarg);
case 'c': // 模拟出的客户端数目
clients_num = atoi(optarg);
case 'p': // 总的线程个数
thread_nums = atoi(optarg);
case 'u': // 目标url
strcpy(url, optarg);
build_request(url); // 构造请求行
pthread_attr_init(&attr);
//注册信号处理函数
action.sa_handler =
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_t tid[thread_nums];
for (int i = 0; i & thread_ ++i) {
/*创建子线程来对服务器进行连接*/
if(pthread_create(&tid[i] , NULL , bench, NULL) == -1) {
perror("pthread create error.\n");
if(sigaction(SIGALRM, &action, NULL) & 0 ) {
error_die("sigaction:");
alarm(benchtime);
start = 1; // 开始
printf("总的请求数%d\n", request_nums);
printf("连接数%d\n", clients_num);
printf("线程数目%d\n", thread_nums);
while(!timerexpired);
printf("失败次数:%d\n", failed);
printf("成功次数:%d\n", success);
pthread_attr_destroy(&attr);
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
时间太小了,哪有你这么测试的。。
同步到新浪微博
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。linux为什么创建线程后主程序退出了
linux为什么创建线程后主程序退出了
10-01-11 &匿名提问
楼主hzyusijia(田心人土土)本人现在在作的项目是linux下的用到多线程的 ,粗略的估计一下一共有启动了6个子线程,其中有两个线程是用于接收和发送数据的,当session创建时两个线程要启动,如果当会话终止线程要关闭,但现在不知道为什么,第一次启动关闭是正常的,当第2次启动是好的,但关闭时程序会崩溃,并提示&Couldn&#39;t get registers: 没有那个进程.&这样的字样.(我在GDB中调试,一般出现错误,使用where可以了解压站的情况,但现在直接崩溃到GDB调试程序外,我根本不知道哪里出错了)我是用改变线程中的while循环的flag和Thread_join来等待线程结束的(有时在Thread_join前设一个断点程序不会崩溃)在linux中使用pthread_create创建了一个线程,在终端上会显示[New Thread
(LWP 14854)]的消息.当退出时会现示[Thread
(LWP 14854) exited],但第2次再创建线程时这些消息没有被显示到终端上,而且第2次启动时线程的ID是和前面被结束了的线程的ID是一样的,这些和程序的崩溃是否有关是否有哪位高手指点一下,为什么,或者有对关闭应该怎么处理.非常着急,谢谢.问题点数:50、回复次数:4 Top1 楼eqxu(天使联盟) 301.3 线程创建属性pthread_create()中的attr参数是一个结构指针,结构中的元素分别对应着新线程的运行属性,主要包括以下几项:__detachstate,表示新线程是否与进程中其他线程脱离同步,如果置位则新线程不能用pthread_join()来同步,且在退出时自行释放所占用的资源.缺省为PTHREAD_CREATE_JOINABLE状态.这个属性也可以在线程创建并运行以后用pthread_detach()来设置,而一旦设置为PTHREAD_CREATE_DETACH状态(不论是创建时设置还是运行时设置)则不能再恢复到PTHREAD_CREATE_JOINABLE状态.__schedpolicy,表示新线程的调度策略,主要包括SCHED_OTHER(正常、非实时)、SCHED_RR(实时、轮转法)和SCHED_FIFO(实时、先入先出)三种,缺省为SCHED_OTHER,后两种调度策略仅对超级用户有效.运行时可以用过pthread_setschedparam()来改变.__schedparam,一个struct sched_param结构,目前仅有一个sched_priority整型变量表示线程的运行优先级.这个参数仅当调度策略为实时(即SCHED_RR或SCHED_FIFO)时才有效,并可以在运行时通过pthread_setschedparam()函数来改变,缺省为0.__inheritsched,有两种值可供选择:PTHREAD_EXPLICIT_SCHED和PTHREAD_INHERIT_SCHED,前者表示新线程使用显式指定调度策略和调度参数(即attr中的值),而后者表示继承调用者线程的值.缺省为PTHREAD_EXPLICIT_SCHED.__scope,表示线程间竞争CPU的范围,也就是说线程优先级的有效范围.POSIX的标准中定义了两个值:PTHREAD_SCOPE_SYSTEM和PTHREAD_SCOPE_PROCESS,前者表示与系统中所有线程一起竞争CPU时间,后者表示仅与同进程中的线程竞争CPU.目前LinuxThreads仅实现了PTHREAD_SCOPE_SYSTEM一值.pthread_attr_t结构中还有一些值,但不使用pthread_create()来设置.为了设置这些属性,POSIX定义了一系列属性设置函数,包括pthread_attr_init()、pthread_attr_destroy()和与各个属性相关的pthread_attr_get---/pthread_attr_set---函数.建议楼主修改一下属性Top2 楼hzyusijia(田心人土土) 回复于
10:38:39 得分 0哪些属性会和关闭有关呢,?这边没有将线程分离,是连接的线程,应该可以用JOIN的吧,现在在pthread_join()前设个断点,单步调试是可以的,但没有断点次次都崩溃,真是奇怪呀.Top3 楼runner001_cn(柳生007) 20把你的pthread_create的写法贴出来啊4 楼hzyusijia(田心人土土) 回复于
13:02:06 得分 0Thread::Thread( bool bDetach )m_bDetach = bDm_bStart =pthread_attr_init( &m_tThreadAttr );if (m_bDetach)pthread_attr_setdetachstate( &m_tThreadAttr, PTHREAD_CREATE_DETACHED );elsepthread_attr_setdetachstate( &m_tThreadAttr, PTHREAD_CREATE_JOINABLE );void Thread::Start()if (m_bStart)int iResult = pthread_create( &m_tThread, &m_tThreadAttr, (tc_thread_func)ThreadRun, this );m_bStart =Thread::Thread( bool bDetach )使用的实参都是false.相关问题
请登录后再发表评论!

我要回帖

更多关于 i7怎么关闭超线程 的文章

 

随机推荐