完成端口中多线程数据读写问题

cctime 2004-11-24 01:22:17
线程情况:A、B是IO完成处理线程,C是连接检查线程;
数据结构:一个客户连接socket对应一个socket_context,一次IO对应一个io_context;
有以下情景:
1、为了接收客户端的一个请求,必须发出2次WSARecv(),这两次IO请求完成后必须将收到的数据合并到一起保存到socket_context里;这2次的完成处理可能分别在A、B两个线程里执行,所以A、B线程在读写同一个socket_context时,必须处理好同步关系;这里我用InterlockedXXX()函数改变socket_context中的标记量实现。
2、当某个连接很久不发送某一种特定的数据时,C线程就会将该连接关闭,关闭时当然最好马上把socket_context清理掉;但是,C线程在做这个操作时,如果A/B正在读写socket_context就麻烦了。问题就是这里该如何处理最恰当?
...全文
890 49 打赏 收藏 转发到动态 举报
写回复
用AI写文章
49 条回复
切换为时间正序
请发表友善的回复…
发表回复
flashboy 2005-03-18
  • 打赏
  • 举报
回复
我想垃圾回收解决方法是不是这样的: ??

1。首先从设计上避免同时WSARECV和WSASEND
2。多个线程间对context的操作访问时候,不加锁直接访问,而且连接断开后:不释放context空间,只设置标志。如果这时候有其他线程返问,先判断下标志再使用。就算连接断开的时候还没来得及设定标志也没关系,因为此时SOCKET操作肯定会失败,你一样也能知道连接已经出错了。
3。每次新建立连接的context自动加到一个FIFO的队列尾。
4。应该有一个垃圾回收器,怎么识别哪些context该回收呢? 应该回收的数 N = FIFO队列数 - 当前连接数 。 从FIFO队列出队前N个就是要回收的垃圾节点。

不知道想的是否正确,请大侠批评指正
flashboy 2005-03-18
  • 打赏
  • 举报
回复
垃圾回收机制这个名词应该比较容易找得到解释,如今在火暴的.NET 和 JAVA中的都是很流行的名词,我来照抄一段吧:
垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能。
垃圾收集的算法分析

Java语言规范没有明确地说明Jvm使用哪种垃圾回收算法,但是任何一种垃圾收集算法一般要做2件基本的事情:

(1)发现无用信息对象;
(2)回收被无用对象占用的内存空间,使该空间可被程序再次使用。

大多数垃圾回收算法使用了根集(root set)这个概念;所谓根集就是正在执行的Java程序可以访问的引用变量的集合(包括局部变量、参数、类变量),程序可以使用引用变量访问对象的属性和调用对象的方法。垃圾收集首选需要确定从根开始哪些是可达的和哪些是不可达的,从根集可达的对象都是活动对象,它们不能作为垃圾被回收,这也包括从根集间接可达的对象。而根集通过任意路径不可达的对象符合垃圾收集的条件,应该被回收。下面介绍几个常用的算法。

1、引用计数法(reference counting collector)

引用计数法是唯一没有使用根集的垃圾回收得法,该算法使用引用计数器来区分存活对象和不再使用的对象。一般来说,堆中的每个对象对应一个引用计数器。当每一次创建一个对象并赋给一个变量时,引用计数器置为1。当对象被赋给任意变量时,引用计数器每次加1。当对象出了作用域后(该对象丢弃不再使用),引用计数器减1,一旦引用计数器为0,对象就满足了垃圾收集的条件。

基于引用计数器的垃圾收集器运行较快,不会长时间中断程序执行,必须实时运行。但引用计数器增加了程序执行的开销,因为每次对象赋给新的变量 ,计数器加1,而每次现有对象出了作用域生,计数器减1。

2、tracing算法(tracing collector)

tracing算法是为了解决引用计数法的问题而提出,它使用了根集的概念。基于tracing算法的垃圾收集器从根集开始扫描,识别出哪些对象可达,哪些对象不可达,并用某种方式标记可达对象,例如对每个可达对象设置一个或多个位。在扫描识别过程中,基于tracing算法的垃圾收集也称为标记和清除(mark-and-sweep)垃圾收集器。

3、compacting算法(compacting collector)

为了解决堆碎片问题,基于tracing的垃圾回收吸收了compacting算法的思想,在清除的过程中,算法将所有的对象移到堆的一端,堆的另一端就变成了一个相邻的空闲内存区,收集器会对它移动的所有对象的所有引用进行更新,使得这些引用 在新的位置能识别原来 的对象。在基于compacting算法的收集器的实现中,一般增加句柄和句柄表。

4、coping算法(coping collector)

该算法的提出是为了克服句柄的开销和解决堆碎片的垃圾回收。它开始时把堆分成一个对象面和多个空闲面,程序从对象面为对象分配空间,当对象满了,基于coping算法的垃圾收集就从根集中扫描活动对象,并将每个活动对象复制到空闲面(使得活动对象所占的内存之间没有空闲洞),这样空闲面变成了对象面,原来的对象面变成了空闲面,程序会在新的对象面中分配内存。

一种典型的基于coping算法的垃圾回收是stop-and-copy算法,它将堆分成对象面和空闲区域面,在对象面与空闲区域面的切换过程中,程序暂停执行
CompletionPort 2005-03-17
  • 打赏
  • 举报
回复
mark
BigFanTian 2005-03-17
  • 打赏
  • 举报
回复
删除的操作是一致的啊,就是删除的时候类似处于写状态而以
click2004 2004-12-06
  • 打赏
  • 举报
回复
关注
leaber 2004-12-02
  • 打赏
  • 举报
回复
顶一下
williamxia8 2004-12-02
  • 打赏
  • 举报
回复
谁给个完整的服务器和客户端的例子,有分感谢,xpxia85@sohu.com
elssann 2004-12-02
  • 打赏
  • 举报
回复
回复人: stonex_2000(三棱镜) ( ) 信誉:101 2004-12-01 22:09:00 得分: 0


呵呵,我也不知道什么是垃圾回收机制,
但驱动中常使用的后备链表(旁视列表)应该是他们所说的那个东东。


-------------------------------------------
你说的LOOKASIDE链表是用来实现内存池的,和这个木有关系
click2004 2004-12-02
  • 打赏
  • 举报
回复
好帖收藏
stonex_2000 2004-12-01
  • 打赏
  • 举报
回复
呵呵,我也不知道什么是垃圾回收机制,
但驱动中常使用的后备链表(旁视列表)应该是他们所说的那个东东。
cctime 2004-12-01
  • 打赏
  • 举报
回复
怎么半天还没说“垃圾回收机制”怎么回事啊?
redchina 2004-11-30
  • 打赏
  • 举报
回复
quote:
elssann(臭屁虫和他的开心果) ( )

采用类似垃圾回收机制一样,,,做一个FIFO
----------------------------------------------------------------------------------------
如果我的理解没有错误的话,用一个链表可以实现类似的功能,只是我没把这个抽象到垃圾回收的机制上来。只是这个好像跟同步不同步没什么关系吧?
cctime 2004-11-30
  • 打赏
  • 举报
回复
垃圾回收机制和计数器到底不同在哪里啊?
sunhuiNO1(2B) 为什么说半句就跑了呢?
elssann 2004-11-30
  • 打赏
  • 举报
回复
回复人: redchina(风清云淡) ( ) 信誉:98 :


这样做过的人比如sunhuiNO1(2B) 我一说是垃圾回收机制他就知道。。。。
redchina 2004-11-30
  • 打赏
  • 举报
回复
elssann(臭屁虫和他的开心果) ,那你说说你怎么搞得?思路?垃圾回收,总有个具体思路吧?
elssann 2004-11-30
  • 打赏
  • 举报
回复
谁说++指令是原子操作啊, ,,
如果是原子操作,MS还要设计InterlockXXX这些函数干虾米?
redchina 2004-11-30
  • 打赏
  • 举报
回复
to cctime()
++指令当然不是原子操作。有可能被别的线程中断。 偶本来想抛砖引玉的,没想到迎来你的板砖…),玉在谁那里呢?在sunhuiNO1(2B) 那里,因为他说了他知道~~~不过我看了
elssann(臭屁虫和他的开心果) 说是 垃圾回收机制 ,名字听说过,还不知道怎么实现~~~~

我自己是这么来做的:工作者线程和检测线程之间没有同步,但是工作者线程之间是同步的。
context资源中的时间变量timecount,检测线程每隔5秒遍历所有资源,资源的timecount+=5;
if(timecount>120)//空闲时间2分钟。
PostQueuedCompletionStatus();//向完成端口发送一个断开该连接的标志
(这种情况下即使我读到的是垃圾数据,也没关系,比如当我刚刚把timecount读出的时候,工作者线程将timecount=0)

当工作者线程首先收到检测线程的结束请求。响应该请求,在同步机制的保护下(比如CRITICAL_SECTION)检测
if(timecount>120)
delete context;在这里进行真正的删除。
也就是说,当检测线程偶然发出错误的删除请求,但是该请求并没有被真正的响应。
cctime 2004-11-30
  • 打赏
  • 举报
回复
sunhuiNO1(2B) 来了就多说几句嘛,please
垃圾回收机制具体是怎么回事?
关于对同一个socket发出>=2个WSASend/WSARecv确实是设计问题,我已经改进;
现在剩下socket_context删除和同步访问问题了。
barsteng 2004-11-29
  • 打赏
  • 举报
回复
呵呵,如果是2个CPU,我真的建议你把并发线程数设置成1个,我的程序在2个CPU的服务器上运行的时候,出了问题,就是一个context会同时被2个线程处理,后来设置成1个就好了,并不影响性能,我的教训,供你借鉴
sunhuiNO1 2004-11-29
  • 打赏
  • 举报
回复
这里发送的处理很麻烦,调试困难。中间出了一些问题,不过后来基本都解决了,
加载更多回复(29)

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧