多线程网络编程中的怪异问题

小弟在项目中碰到一个十分怪异的多线程同步问题,调试几天未有结果,望大虾们分析指点一二,分数管够。
问题描述:
我编写的是一个消息中间件服务器程序。此服务器的一个测试用例是,一个客户端client1发送消息到服务器中的一个消息队列,其余两个客户端client2和client3从队列中接收消息。服务器中的每个消息,只有被client2和client3都接收后才被删除。

假如,服务器的线程2对应于client2,服务器的线程3对应于client3,线程2从socket缓冲区中取得client2这个名字字符串,然后根据client2从队列中取出需要发送给client2的消息,线程3处理client3也是如此。

需要说明的是,每一个线程都使用各自独立的socket。在程序中使用关键代码段来保证各线程的同步工作。

现在的问题是,在程序运行一段时间( <1s )后,线程2有时候从socket缓冲区中取到的用户名字不是client2,而是client3,从而导致了程序的崩溃。
逐步打印调试信息发现,如果线程2从socket缓冲区取到的不是client2而是client3,那么线程2在进入到delMsg()(此函数用来删除队列中的某个消息),并调用EnterCriticalSection(&m_hMutex)加锁后,线程挂起(可能是时间片到?),在接下来,此线程醒来后,竟然不继续从上次断点执行,而是转执行其他的函数!!
不知道这是什么原因?

附:我使用GetCurrentThreadId()来判断当前由哪个线程执行代码,不知道这个函数获得的线程ID是系统唯一的而且是不随时间改变的吗?

我打印的调试信息如下:
从下面可以看到,本来线程3024是处理client13的,但是在下面有一段竟然处理
client12!!!
Thread ID:#3024:client13进入popTopicMessage()
Thread ID:#3024:指向头节点,此用户接收了一圈回到了头节点
Thread ID:#3024:the msg is:client11 says:hi 2
Thread ID:#3024:client13离开popTopicMessage()--success

Thread ID:#3296:client12进入popTopicMessage()
Thread ID:#3296:指向头节点,此用户接收了一圈回到了头节点
Thread ID:#3296:the msg is:client11 says:hi 2
Thread ID:#3296:client12离开popTopicMessage()--success

-----就是在下面一行,3024竟然处理client13:-----
Thread ID:#3024:client12进入deleteMsg()
Thread ID:#3024:server的用户数:2
Thread ID:#3024:节点的消息为:client11 says:hi 2
Thread ID:#3024:增加后的引用计数为1
Thread ID:#3024:client12离开deleteMsg()--success

Thread ID:#3024:client13进入popTopicMessage()
Thread ID:#3024:the msg is:client11 says:hi 2
Thread ID:#3024:client13离开popTopicMessage()--success

-----这次处理client13是正确的3296,但是程序到此就终止了:-----
Thread ID:#3296:client12进入deleteMsg()
Thread ID:#3296:server的用户数:2
[1826 byte] By [songxin328-masm] at [2008-1-9]
# 1
检查下你的SOCKET模型、线程同步
eboy0320-小猪 at 2007-10-19 > top of Msdn China Tech,专题开发,技术,项目,网络通信...
# 2
> 附:我使用GetCurrentThreadId()来判断当前由哪个线程执行代码

没听说过有这么干的,线程调度不是你应该参与的。
rtdb-东临碣石 at 2007-10-19 > top of Msdn China Tech,专题开发,技术,项目,网络通信...
# 3
to eboy0320(E-辉): 检查下你的SOCKET模型、线程同步
请问该如何检查呢?对于线程同步,程序中,被多个线程访问的函数我都加了锁。
而socket模型我就不知道具体怎么检查了,只是我去掉了scoket的延迟特性,即scoket没有使用nagle算法来缓存将要发送的数据。请问,如果要检查socket模型,该从哪几个方面着手呢?

to: rtdb(东临碣石) :
“我使用GetCurrentThreadId()来判断当前由哪个线程执行代码”,指的是我在调试的时候,通过打印GetCurrentThreadId()来人工判断屏幕上的调试信息是由那个线程打印的,进而判断在那个时候是由哪个线程执行代码。前面可能是我叙述不准确,还望见谅哦
songxin328-masm at 2007-10-19 > top of Msdn China Tech,专题开发,技术,项目,网络通信...
# 4
楼主有心,我就多说两句。
你现在只有一个消息队列,有两个人来拿,不知道若是一个人没来拿,另一个人连续拿的情况你是怎么处理的?
其实我觉得你直接开两个消息队列就好了,消息进来时同时进两个队列,读的时候则各人拿各个的,整个系统会变得简单多。
rtdb-东临碣石 at 2007-10-19 > top of Msdn China Tech,专题开发,技术,项目,网络通信...
# 5
感谢rtdb关注此贴
我所实现的是JMS规范,不过是c++语言实现。
按照JMS,主要有两种模式的消息传输, 点对点 和 发布订阅
我现在遇到的问题出现在发布订阅模式中。如果有两个client订阅某主题(既一条队列),则队列本身会保证只有当所有的订阅者收到消息后才会将消息删除,并且队列会有一个map<string,int>来保证client来收时从上次接受的位置收起。

这些都是项目的要求。
网络+多线程,我调试了很久都无法搞定~
只有依赖各位朋友多多帮忙了。
songxin328-masm at 2007-10-19 > top of Msdn China Tech,专题开发,技术,项目,网络通信...
# 6
多线程的socket并发问题,
偶觉得应该是消息队列是加锁共享的,
服务器使用一个监听socket,每接收到一个新的连接,用接收到的socket创建一个新线程。
这样,服务端除监听socket外,其它每个socket都对应一个客户端的连接,
这也就可能需要每一消息都去维护一个客户连接队列。

# 7
我觉得你应该有个消息分发的机制,就是说有一个线程(或过程)读取消息队列,然后根据消息的目的地来分配给client2 或 client3
firebolt2002-霹雳 at 2007-10-19 > top of Msdn China Tech,专题开发,技术,项目,网络通信...
# 8
没有解决,我还是结贴算了。
失望。
songxin328-masm at 2007-10-19 > top of Msdn China Tech,专题开发,技术,项目,网络通信...