小春网

 找回密码
 注册账号
楼主: bakerwhy
收起左侧

[IT 交流] ~~求助~~关于多线程的问题~~

[复制链接]
发表于 2011-11-30 23:25:11 | 显示全部楼层
憨吃迷糊睡 发表于 2011-11-30 22:09
迷糊估计的问题以及考虑的解决办法:

1)在output_data_2_file函数中是否调用了类似于flush这样的函数,把 ...

有意思,查了许久查不出结果。明天去单位写写看看。感觉斑竹是大拿。

点评

额,你和楼主是一个人吗,O(∩_∩)O~  发表于 2011-12-1 21:21
回复

使用道具 举报

发表于 2011-12-1 01:01:48 | 显示全部楼层
本帖最后由 microyzy 于 2011-12-1 01:12 编辑
bakerwhy 发表于 2011-11-30 21:04
我再补充描述一下问题吧
首先这不是一个线程调度的问题,也不存在同步的问题
举个例子,以下代码,

据我所知,你说的情况是不可能出现的。
在同一个线程里,不会出现后面的代码比前面代码先执行的情况,如果这样,多线程就失去了存在的意义,这个和线程之间的调度没有关系。
线程切换最基本的就是保护现场和恢复现场,操作系统如果达不到100%,就没人敢用这个操作系统了。

像lz上面举的例子,同一个线程肯定是i从0到999,然后k从0到999,不会有其他情况。
即使是多个线程同时执行这两个循环,对某一个线程来说,输出顺序也是同样的。但如果i,k是全局变量,就会有同步的问题了。
lz已经测试过?

至于你的真实程序出现那样奇怪的结果,可能是你对程序结构还有理解不对的地方。
另外,是否在中间的输出有什么缓冲区管理之类的,或者有调用第三方的程序什么的,他们的实现有可能不是多线程安全的,就可能会有问题。但如果的确是一个线程,应该不会有这种乱序问题。

评分

参与人数 1 +30 收起 理由
憨吃迷糊睡 + 30 赞一个

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2011-12-1 01:58:14 | 显示全部楼层
憨吃迷糊睡 发表于 2011-11-30 22:09
迷糊估计的问题以及考虑的解决办法:

1)在output_data_2_file函数中是否调用了类似于flush这样的函数,把 ...

多谢糊涂的建议.
1)文件都不大,所以没有使用带缓冲的文件流方式,不过可以考虑试试看,多线程中确实最好不要使用stdio
2)的方法不能很好解决问题,原因就是3)所示的问题,前面生成数据是有依赖性的,就是说后面生成的数据会依赖前一次的数据,读的时候我可以设置循环,直到读取成功为止,但生成数据的时候这样处理的话它会直接跳过,进行下一次处理,显然,一旦跳过,后面的数据都将不正确,而如果设置循环的话,由于顺序的问题,可能会出现死循环,本来在等1的结果,但实际操作流却跳到了3,而3又需要等待2的结果,2又再等待1的结果,该处理1的却进入到3的处理了,这样就形成死循环~~~(不好意思,写得有点乱,不太容易理解)
3)那个现象很奇怪也很难重现,我在pc上做了个模拟的小程序,始终不能重现,用Sleep()来延长时间,又在其中加stdio操作,依旧不能重现,明天去试试用win32的io操作来替代stdio操作。

对9楼的情况,我试图做了如下的一段例子来重现,但并没有出现那个现象
void output_data(int gnr)
{
        int i;
        char filename[256];
        int temp, temp2;
        FILE *fp; //ファイル・ポインター
       
        for(i = 0; i < 256; i++)
                filename = '\0';
       
        strcpy(filename, "test");
       
        //100の位の数字設定
        temp = (gnr + 1) / 100;
        filename[4] = 48 + temp;
        temp2 = (gnr + 1) - (temp * 100);
       
        //10の位の数字設定
        temp = temp2 / 10;
        filename[5] = 48 + temp;
        temp2 = temp2 - (temp * 10);

        temp = temp2;
        filename[6] = 48 + temp;

        strcat(filename, ".dat");
        fp = fopen(filename, "wb");
       
        fprintf(fp, "%d\n", gnr);

        for(i = 0; i <= gnr; i++) {
                fprintf(fp, " %5d  : ", i);
        }
       
        fclose(fp);
        printf("file ok :%d\n", gnr);
}
void fileout()
{
    for(int i=0; i<99;i++)
    {
        //printf("count 1 at :%d\n", i);
        output_data(i);
        //Sleep(2000);
        printf("file ok(fileout func) :%d\n", i);
    }
}

void cout1()
{
    for(int i=0; i<100;i++)
    {
        printf("count 1 at :%d\n", i);
        Sleep(20);
    }
}

void cout2()
{
    for(int i=0; i<100;i++)
    {
        printf("count 2 at :%d\n", i);
        Sleep(20);
    }
}

DWORD WINAPI mycount(LPVOID param)
{
    fileout();
    cout1();
    cout2();
    MessageBox(NULL,L"test",L"test",MB_OK);
    return 0;
}
运行起来会等cout1,cout2的计数完成后才弹出messagebox,但把MessageBox(NULL,L"test",L"test",MB_OK);加到我项目中线程入口函数的最后一行,线程一激活,立马就弹出来。。。
继续解决中。。。。。
回复

使用道具 举报

 楼主| 发表于 2011-12-1 02:44:28 | 显示全部楼层
microyzy 发表于 2011-12-1 01:01
据我所知,你说的情况是不可能出现的。
在同一个线程里,不会出现后面的代码比前面代码先执行的情况,如果 ...

在一个线程内应该是不会出现这种情况的,我给的那个只是为了说明问题,但我遇到的确实就是这种情况,13#我做了个测试例子,却一直没有重现,但在我的项目中,确实那个对话框立刻就弹出了,而且弹出后,查看文件系统会发现文件还在生成过程中(文件的生成按说应该先于对话框的弹出)
确实有调用第三方的GIS库函数,等等,,,,,,我好想明白了点什么
多谢~~~~~太感谢了,多谢你的提醒。。。。。。。明天去试试,有结果了告知原因。。。。。。
回复

使用道具 举报

发表于 2011-12-1 21:24:46 | 显示全部楼层
憨吃迷糊睡 发表于 2011-11-30 22:09
迷糊估计的问题以及考虑的解决办法:

1)在output_data_2_file函数中是否调用了类似于flush这样的函数,把 ...

我和楼主不是一个人,哪有那闲工夫整两个演戏啊。只是对楼主所提的现象感兴趣,查了查,不知道原因。今天上班太忙了,竟然忘了实验一下。
回复

使用道具 举报

发表于 2011-12-1 22:22:46 | 显示全部楼层
bakerwhy 发表于 2011-11-30 20:38
不好意思,可能是我没有描述清楚,我给出的threadFunc()里所有执行绪都是在一个线程中进行的,这个线程是 ...

不知你是否真的有在子线程里进行画面操作?
如果有那你可以删掉画面操作试试.
如果真的有必要一边计算一边进行画面操作,
那是否应该发消息通知主线程来处理?



回复

使用道具 举报

发表于 2011-12-1 22:40:33 | 显示全部楼层
纯粹是过来拜膜下楼上IT高手

评分

参与人数 1 +1 收起 理由
憨吃迷糊睡 + 1 法王大人好

查看全部评分

回复

使用道具 举报

发表于 2011-12-1 23:00:01 | 显示全部楼层
多线程的东西最搞不清楚了,楼主的多个进程里用的方法都是thread safe的吗?有奇怪的函数的话可能会有问题。以前做的一个项目也是多线程然后有奇怪的问题,好像是sleep时间会错乱掉,结果和操作系统有关。后来怎么搞定的我也忘了,反正不是我搞定的[.6D484A04.]
楼主可不可以在前一个处理中调用后面一个函数呢(比如在dealwith里调用get_result_from_10_files)
或者做个简单的eventobserver,监视各个事件的进行情况来调用函数。
回复

使用道具 举报

 楼主| 发表于 2011-12-2 23:58:13 | 显示全部楼层
经过这两天的解决,问题找到了,原因是因为在这个线程中调用 的第三方库GEOElement成员函数后出现问题,把那几行注释掉就不会出现这个问题了~~~
剩下的问题就更不好解决了,GeoElemant提供的是lib,不能修改,但又必须要用。。。。。
好吧,谢谢各位的关注,问题找到后面总会有解决方案的。。。。。。

特别感谢microyzy的提醒。。。。
回复

使用道具 举报

发表于 2011-12-4 11:50:17 | 显示全部楼层
bakerwhy 发表于 2011-12-2 23:58
经过这两天的解决,问题找到了,原因是因为在这个线程中调用 的第三方库GEOElement成员函数后出现问题,把 ...

好像一般第三方库都提供好几种版本的LIB吧,要不找找试试?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小春网
常务客服微信
微信订阅号
手机客户端
扫一扫,查看更方便! 快速回复 返回顶部 返回列表