免费注册 查看新帖 |

Chinaunix

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

请教下线程的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-18 23:54 |只看该作者 |倒序浏览
20可用积分
int liFrom = 0;
        int liTo = 0;
        int liSocket = 0;
        int liFileLen = 0;
        int liSCode = 0;
        int liRet = -1;

        InfoHead *lpHt = static_cast<InfoHead*>(avOpt);
        if (lpHt == NULL)
        {
                cout<<"lpHt is NULL"<<endl;
                return NULL;
        }

        liFrom = lpHt->siFrom;
        liTo = lpHt ->siTo;

        liSocket = lpHt->spHp->ConnectSrv();
        if (liSocket == 0)
        {       
                return NULL;
        }
cout<<"liForm:"<<liFrom<<" liTo:"<<liTo<<endl;  //////////////////////////////////1
        liRet = lpHt->spHp->SendRequest(liSocket, liFrom, liTo);/////2
        if (liRet != 0)
        {
                cout<<"send request failed!!"<<endl;
                tcp_close(liSocket);

                return NULL;
        }
        liRet = lpHt->spHp->ReceiveResp(liSocket, liFileLen, liSCode);
        if (liRet != 0)
        {
                cout<<"send request failed!!"<<endl;
                tcp_close(liSocket);

                return NULL;
        }
       
        return NULL;

}

我开启五个线程运行时,就发现这些局部变量全部是一样的值了, 把每个线程sleep 2s后再开启的话就可以了
由此可以看出是变量访问冲突了!!
也就是线程互斥
此有几点疑问:
难道这几个线程的局部变量全部是共享的??
如果用线程互斥的话,这五个线程还同时运行吗??多线程同时运行还有意义吗??

对线程认识不深,请各位指点!!

最佳答案

查看完整内容

大胆的猜测下你的线程创建和参数使用方式:for (i = 0; i < threadNum; i++) { avOpt->siFrom = f(i); /* siFrom是i的函数,即f(i) */ avOpt->to = g(i); /* 解释同上 */ /* 其它初始化部分 ... */ assert(pthread_create(&tid, NULL, worker, avOpt) == 0);}如此形式的参数使用方式,就会有问题,因为calling thread的pthread_create返回继续运行和线程worker开始运行已经分别是独立的过程,由系 ...

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
2 [报告]
发表于 2008-11-18 23:54 |只看该作者

回复 #8 chary8088 的帖子

大胆的猜测下你的线程创建和参数使用方式:
for (i = 0; i < threadNum; i++) {
      avOpt->siFrom = f(i); /* siFrom是i的函数,即f(i) */
      avOpt->to = g(i); /* 解释同上 */
      
      /* 其它初始化部分 ... */
      
      assert(pthread_create(&tid, NULL, worker, avOpt) == 0);
}
如此形式的参数使用方式,就会有问题,因为calling thread的pthread_create返回继续运行和线程worker开始运行已经分别是独立的过程,
由系统调度决定运行顺序,所以不应该假设:
下次for循环的赋值语句执行时,上次创建的线程worker已经执行了
            liFrom = lpHt->siFrom;
        liTo = lpHt ->siTo;
即存在一种情况:所有线程创建完毕时,各线程还没有执行上面这两句,此时avOpt->siFrom avOpt->to使用了最后一次for循环的赋值,
最终所有线程都使用了同样的liFrom liTo。

解决方法:avOpt->siFrom avOpt->to应使用全局数组或静态数组或堆内存

论坛徽章:
0
3 [报告]
发表于 2008-11-19 00:16 |只看该作者
局部变量不存在多线程访问冲突的问题,每个线程的函数栈中都有一份拷贝,查找其它原因吧

论坛徽章:
0
4 [报告]
发表于 2008-11-19 00:22 |只看该作者
这个代码用了什么库?没看出线程在哪里。

线程的局部变量是私有的。全局变量是共享的。你说那些变成相同的可能是全局变量。

用线程互斥是在关键时刻把并发转为顺序执行。但其它大部分不互斥的时候,还是可以并发处理的。

论坛徽章:
3
戌狗
日期:2014-09-10 17:07:162015年辞旧岁徽章
日期:2015-03-03 16:54:15wusuopu
日期:2016-06-17 17:43:45
5 [报告]
发表于 2008-11-19 00:49 |只看该作者
原帖由 chary8088 于 2008-11-18 23:54 发表
int liFrom = 0;
        int liTo = 0;
        int liSocket = 0;
        int liFileLen = 0;
        int liSCode = 0;
        int liRet = -1;

        InfoHead *lpHt = static_cast(avOpt);
        if (lpHt == NULL)
        {
                coutConnectSrv(); ...

InfoHead *lpHt = static_cast<InfoHead*>(avOpt);这个得到的是局部变量?从贴出的代码看不出来。

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
6 [报告]
发表于 2008-11-19 02:12 |只看该作者

回复 #1 chary8088 的帖子

先区分哪些变量需要共享,修改共享变量需要加锁。你这个程序看似处理network IO,属于CPU-Bound和IO-Bound结合类型,典型的多线程使用场合,即使是单处理器,只要线程锁的粒度合适,可以提高并发性能和加快IO响应时间。

你提到“我开启五个线程运行时,就发现这些局部变量全部是一样的值了”,是指下面这句代码打印的结果吗?
“cout<<"liForm:"<<liFrom<<" liTo:"<<liTo<<endl; ”
如果是,那么:
        liFrom = lpHt->siFrom;
        liTo = lpHt ->siTo;
这两句的 lpHt->siFrom;lpHt ->siTo;在何处初始化的?

论坛徽章:
0
7 [报告]
发表于 2008-11-19 06:24 |只看该作者

回复 #1 chary8088 的帖子

每个线程的资源是8k(1kpcb+7个内核堆栈)+4G的虚存(用户空间)。

虚存的东西是共享的。

论坛徽章:
0
8 [报告]
发表于 2008-11-19 09:16 |只看该作者

回复 #5 timespace 的帖子

int liFrom = 0;
        int liTo = 0;
        int liSocket = 0;
        int liFileLen = 0;
        int liSCode = 0;
        int liRet = -1;

        InfoHead *lpHt = static_cast<InfoHead*>(avOpt);//avOpt 是线程参数
        if (lpHt == NULL)
        {
                cout<<"lpHt is NULL"<<endl;
                return NULL;
        }

        liFrom = lpHt->siFrom;//在这里初始化,lpHt->siFrom;是传进来的
        liTo = lpHt ->siTo;     

        liSocket = lpHt->spHp->ConnectSrv();//调用的外部函数返回的值,也就是获取socket
        if (liSocket == 0)
        {        
                return NULL;
        }
cout<<"liForm:"<<liFrom<<" liTo:"<<liTo<<endl;  //////////////////////////////////1
        liRet = lpHt->spHp->SendRequest(liSocket, liFrom, liTo);/////2
        if (liRet != 0)
        {
                cout<<"send request failed!!"<<endl;
                tcp_close(liSocket);

                return NULL;
        }
        liRet = lpHt->spHp->ReceiveResp(liSocket, liFileLen, liSCode);
        if (liRet != 0)
        {
                cout<<"send request failed!!"<<endl;
                tcp_close(liSocket);

                return NULL;
        }
        
        return NULL;

}

我开启多个线程后,liFrom,liTo值是一样的了,按说局部变量是每个线程私有的

论坛徽章:
0
9 [报告]
发表于 2008-11-19 09:29 |只看该作者
这两句的 lpHt->siFrom;lpHt ->siTo;在何处初始化的?

这两句的值是在线程函数外部初始化的,但是到线程函数里面,我把它赋值给线程函数里面的局部变量了,不应该有冲突了

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
10 [报告]
发表于 2008-11-19 09:43 |只看该作者
那就看看你lpHt->siFrom; 这个值是不是每个本程传进行的参数都是一样的呗.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP