免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: Dannysd
打印 上一主题 下一主题

[C] 同一个sock fd上两个线程同步问题 [复制链接]

论坛徽章:
4
双子座
日期:2014-08-28 10:08:002015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:58:112015年亚洲杯之阿联酋
日期:2015-03-13 03:25:15
11 [报告]
发表于 2014-04-15 15:27 |只看该作者
首先recv返回-1不是代表断开,至少在一些情况下不是,其次为什么要分开读写呢,其实大多是情况下send的函数的性能很高的,基本上是10几个微妙的水平,分开2个线程反而加重了cpu的调度,性能真的好吗?

论坛徽章:
6
酉鸡
日期:2013-11-04 15:30:02巳蛇
日期:2014-01-23 10:36:23双鱼座
日期:2014-01-23 13:08:332015亚冠之鹿岛鹿角
日期:2015-09-03 14:36:002015亚冠之武里南联
日期:2015-09-18 10:48:1315-16赛季CBA联赛之山西
日期:2016-05-05 00:05:33
12 [报告]
发表于 2014-04-15 16:35 |只看该作者
回复 11# weishuo1999


    自始至终都没提过性能两个字

    帖子明显没有问recv函数的应用

    你看我都不知道说什么好了。。。。。。。。。。。

   

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
13 [报告]
发表于 2014-04-15 16:48 |只看该作者
折腾, 请用两个socket...

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
14 [报告]
发表于 2014-04-15 18:10 |只看该作者
回复 1# Dannysd
大神们的建议是合理的,但老板估计不愿听“这代码太垃圾,要彻底重写”。

几个建议:
1. 线程同步是必须的。这关系到程序逻辑的正确性,和架构无关。

2. 简化同步逻辑。A(收线程)做主动控制,B(发线程)做被动响应。以连接状态为例,只能由A修改,B只读。

3. 伪代码。quick & dirty的fix大概就是这样,细节上你继续完善吧。
  1. /*
  2. * conn_mutable信号量初值为0,连接状态是否可修改
  3. * conn_ready信号量初值为0 ,连接是否就绪
  4. * conn_ok初值为false,推荐__atomic / __sync存取
  5. */
  6. void *thread_recv(void *arg)
  7. {

  8. while (!sys_exit) {
  9.      sem_wait(&conn_mutable);
  10.      reconnect(); /* 如果fd已打开,先关闭 */
  11.      conn_ok = true;
  12.      sem_post(&conn_ready);

  13.      while (1) {
  14.           ret = recv(fd, …);
  15.           if (ret > 0) {
  16.                /* 正常接收 */
  17.           } else if (ret == 0 ) {
  18.                /* 正常关闭 */
  19.           } else {
  20.                if (errno == EINTR || errno == EAGAIN) continue;
  21.                conn_ok = false;
  22.                break;
  23.           }
  24.      }
  25. }

  26. return NULL;
  27. }

  28. void *thread_send(void* arg)
  29. {

  30. while (!sys_exit) {
  31.      sem_post(&conn_mutable);
  32.      sem_wait(&conn_ready);

  33.      while (conn_ok) {
  34.           ret = send(fd, ...);
  35.           if (ret > 0) {
  36.                /* 正常发送 */
  37.           } else {
  38.                if (errno == EINTR || errno == EAGAIN) continue;
  39.                break;
  40.           }
  41.      }
  42. }

  43. return NULL;     
  44. }
复制代码

论坛徽章:
1
巨蟹座
日期:2014-03-18 23:44:30
15 [报告]
发表于 2014-04-15 21:50 |只看该作者
windoze 发表于 2014-04-15 11:05
回复 7# Dannysd

说的就是应用层协议,底下的TCP谁让你去改了。

我感觉读和写放在两个线程是有可取的场景。
比如需要读 M 次, 写 N 次的情况。如果放在一个线程线性执行,势必会在第一次读写完成后才能下一次处理。
此时,如果将读取的数据放入一个缓存,让写线程慢慢从缓存中取数据分发出去,岂不是有提高响应速度!

论坛徽章:
6
酉鸡
日期:2013-11-04 15:30:02巳蛇
日期:2014-01-23 10:36:23双鱼座
日期:2014-01-23 13:08:332015亚冠之鹿岛鹿角
日期:2015-09-03 14:36:002015亚冠之武里南联
日期:2015-09-18 10:48:1315-16赛季CBA联赛之山西
日期:2016-05-05 00:05:33
16 [报告]
发表于 2014-04-15 22:24 |只看该作者
回复 14# timespace


    谢谢timespace,感谢理解啊!!说多了都是泪

    现在已经是接收来实现管理,不过也没用信号量这么高上大的东西

    因为创建有先后顺序,所以不会存在,fd没就绪就读或写的情况

    发送的部分是这样处理的,如果fd被清0,发送失败也没关系,只要free(data)就好了

    (开始想用锁来查看fd,但是如果链接断开,不论当前锁没锁,这个fd都是不可用的,所以无效)

    很粗陋,但也不知道怎么搞好

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
17 [报告]
发表于 2014-04-15 22:25 |只看该作者
回复 15# socay2

那你用一个还是多个写线程?用一个写线程实质上没有提高处理速度,因为读写线程基本没有一起运行的,总是一个等另一个;用多个写线程就有可能导致多个应答乱序,除非你的协议专门处理了这种情况,否则实际上给客户端增加了复杂度而没带来什么好处。
读写分离的场景确实是有的,但很罕见,在TCP这样的流协议上就更罕见。

论坛徽章:
6
酉鸡
日期:2013-11-04 15:30:02巳蛇
日期:2014-01-23 10:36:23双鱼座
日期:2014-01-23 13:08:332015亚冠之鹿岛鹿角
日期:2015-09-03 14:36:002015亚冠之武里南联
日期:2015-09-18 10:48:1315-16赛季CBA联赛之山西
日期:2016-05-05 00:05:33
18 [报告]
发表于 2014-04-15 22:29 |只看该作者
回复 15# socay2


    感谢socay2回复

    就像FTP协议里传输文件一样,就是会一直发送数据,client只要确认收的数据没有错误就好

    并不对server端返回什么数据,就是非常类似于这种情况

论坛徽章:
6
酉鸡
日期:2013-11-04 15:30:02巳蛇
日期:2014-01-23 10:36:23双鱼座
日期:2014-01-23 13:08:332015亚冠之鹿岛鹿角
日期:2015-09-03 14:36:002015亚冠之武里南联
日期:2015-09-18 10:48:1315-16赛季CBA联赛之山西
日期:2016-05-05 00:05:33
19 [报告]
发表于 2014-04-15 22:38 |只看该作者
回复 17# windoze


    一个链接对应一个fd,一个fd对应一读一写两个线程,暂时没想到可能会出现什么问题

    效率暂且不计吧,因为大神们经验是非常丰富的,肯定有各自独到的见解,如果算上的话,势必会引发大争论

    诚然,这个需求确实也比较少见

论坛徽章:
1
巨蟹座
日期:2014-03-18 23:44:30
20 [报告]
发表于 2014-04-15 22:55 |只看该作者
windoze 发表于 2014-04-15 22:25
回复 15# socay2

那你用一个还是多个写线程?用一个写线程实质上没有提高处理速度,因为读写线程基本没 ...

读写线程基本没有一起运行的,总是一个等另一个 为什么要等?发送断只要有数据就发送,接收端只要缓存够就接收。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP