免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 8829 | 回复: 8
打印 上一主题 下一主题

[其他] 多线程如何才能等待任务执行完成才停止 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-05-24 13:00 |只看该作者 |倒序浏览
假设总共有5个线程,其中4个在read中,另一个正在处理任务。

这时候需要停止系统做更新操作等,我希望程序的停止是在这个线程任务处理完成后才正常停止。如何做?谢谢啦~~~~

pthread_cancel只要发送信号到线程了,线程接收到就退出了,那么就会造成有些任务只处理到一半。。。

论坛徽章:
0
2 [报告]
发表于 2013-05-24 13:10 |只看该作者
现在想的是,如果自己在做任务,然后就去注册一下。感觉麻烦,pthread_cancel能解决吗

论坛徽章:
0
3 [报告]
发表于 2013-05-24 13:10 |只看该作者
现在想的是,如果自己在做任务,然后就去注册一下。感觉麻烦,pthread_cancel能解决吗

论坛徽章:
0
4 [报告]
发表于 2013-05-24 13:14 |只看该作者
可以手动设置线程退出的时机。
通过 int pthread_setcanceltype(int type, int *oldtype)
设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和 PTHREAD_CANCEL_ASYNCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和 立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。
此函数应该在线程开始时执行,若线程内部有任何资源申请等操作,应该选择 PTHREAD_CANCEL_DEFFERED 的设定,然后在退出点(pthread_testcancel 用于定义退出点)进行线程退出。
void pthread_testcancel(void)
检查本线程是否处于Canceld状态,如果是,则进行取消动作,否则直接返回。 此函数在线程内执行,执行的位置就是线程退出的位置,在执行此函数以前,线程内部的相关资源申请一定要释放掉,他很容易造成内存泄露。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
5 [报告]
发表于 2013-05-24 13:14 |只看该作者
我还没碰到过要用 pthread_cancel 的场合。

这函数设计出来算一种bug吗?

论坛徽章:
0
6 [报告]
发表于 2013-05-24 13:22 |只看该作者
我大致理解你的运用场景了。一般通用的做法是这样的:
在新线程的入口程序里面通常会有如下代码段:

while(sys_state != SYS_SHUT_DOWN)
{
           if(hasJobs())
           {
            //here process you jobs
           }
           else
            {
               sleep(nnnnn);//等着任务的到来
            }

接下来的代码就是函数返回及线程退出之前的资源回收了
一般都不会主动使用thread_cancel来结束线程。线程执行的代码段结束了,它自己会退出的,你只需要考虑什么时候让它的代码段结束就行了。

论坛徽章:
0
7 [报告]
发表于 2013-05-24 15:02 |只看该作者
回复 4# foolishx

#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void *thread(void* m)
{
        pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL);     //??????
       // pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); //??????
        pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); //??????
        unsigned long  t,id;
        t = *(unsigned long *)m;
        while(1)
        {
                printf("thread %ld\n",pthread_self()); //??????
                sleep(3);
//                pthread_testcancel();
        }
}




int main()
{
        pthread_t t[2];
        pthread_attr_t at;
        int ret, i;
        for(i = 0; i < 2;i++)
        {
                ret = pthread_create(&t,NULL,thread,&i);
                if(ret!=0)
                {
                        printf ("Create pthread error!n");
                        exit (1);
                }
printf("%ld\n", t);




        }
        while(1){
//                pthread_cancel(t[0]); //10???,???????. t??????
//                pthread_cancel(t[1]); //10???,???????. t??????
                sleep(10);
                pthread_cancel(t[1]); //10???,???????. t??????
                pthread_cancel(t[0]); //10???,???????. t??????
        }
}




现在感觉很奇怪




测试代码如上,   如果我给线程1,2都发送了cancel信号,但是由于线程中没有cancel点,所以一直卡在,但为什么printf的都没有打了呢?








如果我在线程1,2都加上pthread_testcancel(),线程没有正常退出,线程也没有打印printf的内容




如果主线程只给一个线程发送cancel信号,则无论有没有pthread_testcancel() 线程都会退出一个。。。。




   

论坛徽章:
0
8 [报告]
发表于 2013-05-29 14:38 |只看该作者
本帖最后由 foolishx 于 2013-05-29 14:39 编辑

回复 7# korpus

先说说你代码里存在的问题:
int main()
{
        pthread_t t[2];
        pthread_attr_t at;
        int ret, i;
        for(i = 0; i < 2;i++)
        {
                ret = pthread_create(&t ,NULL,thread,&i);
                if(ret!=0)
                {
                        printf ("Create pthread error!n");
                        exit (1);
                }
printf("%ld\n", t);




        }
        while(1){
//                pthread_cancel(t[0]); //10???,???????. t??????
//                pthread_cancel(t[1]); //10???,???????. t??????
                sleep(10);
                pthread_cancel(t[1]); //10???,???????. t??????
                pthread_cancel(t[0]); //10???,???????. t??????
        }
}
由于上述代码存在的问题,会导致你丢失了第一个线程的id,于是之后所有对于线程1的操作都将没有办法准确的进行,同时对于t[1]的操作将是不可知的结果 。修正之后再看看问题如何   

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
9 [报告]
发表于 2013-06-14 17:50 |只看该作者
korpus 发表于 2013-05-24 13:00
假设总共有5个线程,其中4个在read中,另一个正在处理任务。

这时候需要停止系统做更新操作等,我希望程 ...

pthread_join();
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP