免费注册 查看新帖 |

Chinaunix

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

[C] epoll的几个操作函数是线程安全吗? 表示怀疑~ [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-07-20 14:32 |只看该作者 |倒序浏览
因为有用过libevent,libevnet里网络io都是单线程里处理。
今天看到一篇《
epoll加线程池》的文章,看到它在线程池里处理完放送消息后,立即调用
ev.events=EPOLLOUT|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_MOD,fd,&ev);

难道这里的epoll_ctl是线程安全的?
如果是的话,那用epoll多线程编程就很方便了, libevent这个问题就很麻烦处理,要用管道解决。

论坛徽章:
0
2 [报告]
发表于 2011-07-20 14:35 |只看该作者
谁说libevent都是单线程的,memcached就是多线程的。另外epoll应该不是线程安全的,你要么加锁,要么每个线程控制一个epoll

论坛徽章:
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
3 [报告]
发表于 2011-07-20 14:38 |只看该作者
本帖最后由 yulihua49 于 2011-07-20 14:41 编辑
因为有用过libevent,libevnet里网络io都是单线程里处理。
今天看到一篇《
epoll加线程池》的文章,看到它 ...
ydfgic 发表于 2011-07-20 14:32



    线程安全的!!!!
惊群是良性的,任何fd都不会分配给多个线程。
可以在不同线程 epoll_ctl和epoll_wait.
因此通常不需要L/F模型。

论坛徽章:
0
4 [报告]
发表于 2011-07-20 15:19 |只看该作者
谁说libevent都是单线程的,memcached就是多线程的。另外epoll应该不是线程安全的,你要么加锁,要么每个线 ...
liexusong 发表于 2011-07-20 14:35


memcached多线程应该是自己做了一些同步机制吧,libevent是线程不安全的,反正。
你和3楼的回答矛盾了啊~ 他说是安全的~

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
5 [报告]
发表于 2011-07-20 15:29 |只看该作者
man里面说epoll的几个函数是线程安全的

论坛徽章:
0
6 [报告]
发表于 2011-07-20 15:39 |只看该作者
线程安全的!!!!
惊群是良性的,任何fd都不会分配给多个线程。
可以在不同线程 epoll_ctl和 ...
yulihua49 发表于 2011-07-20 14:38


谢谢~ 原来epoll_wait也是线程安全的,这样看来epoll真的做的很不错,对开发者非常有好,我会尽量用epoll取代libevent来编程。
另外,这么一来 LF模型就很好实现了,就一个线程池每个线程来 wait --》 handle,连一般的锁都省去了(虽然有群惊现象)。
但我习惯了半同步/半异步的模型,认为将连接层和接收层还有 逻辑处理线程池 分开比较清晰。 知道了epoll_ctrl线程安全,那用多线程处理就方便许多了,以前还要用
pipe传回到接收线程去,真的有点复杂

论坛徽章:
0
7 [报告]
发表于 2011-07-20 15:41 |只看该作者
man里面说epoll的几个函数是线程安全的
hellioncu 发表于 2011-07-20 15:29


说来惭愧,没有好好看man,看到ET 和 LT 就没看下去了

论坛徽章:
0
8 [报告]
发表于 2011-07-20 16:02 |只看该作者
memcached多线程应该是自己做了一些同步机制吧,libevent是线程不安全的,反正。
你和3楼的回答矛盾了 ...
ydfgic 发表于 2011-07-20 15:19



    我也没有man看过,不过线程安全这方面不一定要系统提供,可以自己去实现的

论坛徽章:
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 [报告]
发表于 2011-07-20 16:22 |只看该作者
本帖最后由 yulihua49 于 2011-07-20 16:35 编辑
谢谢~ 原来epoll_wait也是线程安全的,这样看来epoll真的做的很不错,对开发者非常有好,我会尽量用ep ...
ydfgic 发表于 2011-07-20 15:39


给你看看我的任务调度器,很短小,很精彩。
  1. static void *thread_work(void *param)
  2. {
  3. resource *rs=(resource *)param;//线程池指针
  4. int ret,fds;
  5. TCB *task;
  6. struct epoll_event event;

  7.         rs->tid=pthread_self();
  8.         while(1) {
  9. //从就绪队列取一个任务
  10.                 pthread_mutex_lock(&rpool.mut);//非IO事件队列,例如取得连接池后的任务要回到这里等待执行
  11.                 while(!(task=rdy_get())) {//这是一个L/F模型,tpool.rdy_num通常=1,1个Leader。多了无益。
  12.                         if(rpool.flg >= tpool.rdy_num) break;
  13.                         rpool.flg++;
  14.                         ret=pthread_cond_wait(&rpool.cond,&rpool.mut); //没有任务,等待
  15.                         rpool.flg--;
  16.                 }
  17.                 pthread_mutex_unlock(&rpool.mut);
  18.                 if(!task) {//所有没有成为leader的线程都作为follower,全在epoll_wait上竞争。
  19.                         fds = epoll_wait(g_epoll_fd, &event, 1 , -1);
  20.                         if(fds < 0){
  21.                                 ShowLog(1,"%s:epoll_wait err=%d,%s",__FUNCTION__,errno,strerror(errno));
  22.                                 sleep(30);
  23.                                 continue;
  24.                         }
  25.                         task = (TCB *)event.data.ptr;
  26.                         task->events=event.events;
  27. //检查事件是否健康
  28.                         if(!task->call_back && !(event.events&EPOLLIN)) {
  29.                                 do_epoll(task,EPOLL_CTL_DEL);
  30.                                 client_del(task);
  31.                                 continue;
  32.                         }
  33.                 }
  34. //              rs->timestamp=
  35.                 task->timestamp=now_usec();
  36.                 ret=do_work(task);//不论收、发、出错都有统一的工作程序处理。
  37.         }
  38.         ShowLog(1,"%s:tid=%lu canceled",__FUNCTION__,pthread_self());
  39.         mthr_showid_del(rs->tid);
  40.         rs->timestamp=now_usec();
  41.         rs->status=0;
  42.         rs->tid=0;
  43.         return NULL;
  44. }
复制代码

论坛徽章:
0
10 [报告]
发表于 2011-07-20 17:57 |只看该作者
回复 9# yulihua49

确实这段代码很短小精悍

有几个地方小弟分析一下看对不对:
我看到一个 介绍 LF的文章,大致意思是它只有一个 Leader去处理网络请求,然后自己编程 proccesor 处理请求,其余flower会有一个成为leader接替它。
而你的实现里,意思则是相反,一个线程在等待任务队列(tpool.rdy_num= 1),其余线程池里的线程会等待在epoll_wait上,然后会被唤醒处理一个分配的相应事件,
根据这个事件产生task,然后处理这个task。
那么我觉得有两点不合理的地方,
1.如果相应事件过多,超出了wait线程数量,这时候每个线程都会去处理一个task,而这个task的处理事件过长,那么就没有线程在 epoll上等待,会造成网络处理的低效(比如连接拒绝)
2.只有一个线程在等待任务队列,如果同时到达几个任务的时候,就没有及时的线程相应去处理(当然,那些丢任务的线程会去取队列front端的任务,但是万一不及时呢?)
所以我觉得这个模型,潜在的让worker影响到了网络处理。

我想至少要有个线程保证在处理网络输入,而不是自己去做事,应该丢到 任务队列里,排队去。或者靠优先级,让高优先级的直接处理,长时间的丢队列。
其实这样我觉得和HS/HA半同步/半异步模式 差不多了,这个可能更高效点,在线程资源的使用上。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP