免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 4889 | 回复: 20

多线程编程遇到的问题,大家帮忙看看。 [复制链接]

论坛徽章:
0
发表于 2007-09-18 09:14 |显示全部楼层
现在在尝试做一个服务器端的程序,负责与尽可能多的客户端进行交互。
基于linux的嵌入式系统,用c实现。
要实现的功能简单说一下:客户端开启以后,首先向服务器端发消息A,是一个请求登录的消息,服务器端收到之后,进行检查,然后向客户端回应一个消息A~,然后客户端收到之后向服务器发消息B,服务器端收到之后回B~,此后这个过程将一直进行,B~里面就是一些时间和频率的校准信息,目的是实现服务器和客户端的同步。
所有的客户端只能通过一个端口与服务器进行通信,标识消息来源的是消息中包含的Mac地址。
我服务器端现在的处理是:维护一个链表,每一个结点对应一个客户端,结点内包含客户端的Mac地址、一个消息队列和其他一些信息。没收到一个消息,首先判断类型,如果是消息A,说明是一个新的客户端登录,首先我创建一个队列,然后把消息A放到队列中,然后在链表中新增一个结点,然后创建一个线程,把结点指针作为参数传给线程处理函数,以后收到B消息,就通过查找链表,找到相应的客户端对应的结点,从而找到消息队列地址,然后将消息写入队列。主要思路就是主线程负责将消息写到消息对应客户端对应的队列中,然后线程处理函数负责读出消息,然后进行相应处理。
因为刚接触多线程编程,很多东西理解的不到位,可能描述的不准确。
现在主要碰到这样写问题,希望大家帮我看看。
1.怎样才能实现消息队列主线程写和子线程的读不冲突,就是不知道该怎样同步这个消息队列,用互斥锁好像不太可行,如果有500个客户端,那就要建500个锁,而且维护这些锁也比较困难。
2.子线程中碰到异常要推出的话,因为主线程在循环接收消息的处理中,没办法调用pthread_join回收线程资源,这样长时间的话可能不行。

论坛徽章:
0
发表于 2007-09-18 09:22 |显示全部楼层
1. 主线程只进行写操作,子线程只进行读操作;就不会发生冲突,不需要加锁。

论坛徽章:
0
发表于 2007-09-18 09:25 |显示全部楼层
2. 子线程退出之前,给主线程发一个exit消息,主线程在链表中删除该客户对应的结点就可以了。线程的管理调度是OS的事,不需要自己关心。

论坛徽章:
0
发表于 2007-09-18 10:03 |显示全部楼层
原帖由 prc 于 2007-9-18 09:22 发表
1. 主线程只进行写操作,子线程只进行读操作;就不会发生冲突,不需要加锁。

不是很明白,比如队列是空的,刚好主线程写到一半,子线程开始运行,是不是就冲突了?
谢谢!

论坛徽章:
0
发表于 2007-09-18 10:03 |显示全部楼层
原帖由 prc 于 2007-9-18 09:25 发表
2. 子线程退出之前,给主线程发一个exit消息,主线程在链表中删除该客户对应的结点就可以了。线程的管理调度是OS的事,不需要自己关心。

我看书上写如果没有phtread_join的话资源一直不会释放。

论坛徽章:
0
发表于 2007-09-18 10:19 |显示全部楼层
原帖由 oweny 于 2007-9-18 10:03 发表

不是很明白,比如队列是空的,刚好主线程写到一半,子线程开始运行,是不是就冲突了?
谢谢!


主线程先往队列里写,写完之后才更新写指针。
子线程先判读/写指针,确定是否有数据可读,然后将数据读出,最后更新读指针。

像你刚才举的例子,刚好主线程写到一半,子线程开始运行,由于数据还没有写完,主线程不会更新写指针,那么子线程看到的读/写指针都是0,因此就不会去从队列里取出数据。也就不会发生冲突。

论坛徽章:
0
发表于 2007-09-18 10:21 |显示全部楼层
原帖由 oweny 于 2007-9-18 10:03 发表

我看书上写如果没有phtread_join的话资源一直不会释放。

只有线程调用了pthread_exit或者return,那么线程占用的资源就被释放了
pthread_join的作用是挂起当前的线程,等待另外一个线程结束。

论坛徽章:
0
发表于 2007-09-18 10:55 |显示全部楼层
子线程先判读/写指针,确定是否有数据可读,然后将数据读出,最后更新读指针。

有问题的。 在读的时候, 主线程可能继续更新数据。

多线程 不加锁是非常危险的。


提供一点我的服务器架构设计


线程不需要这么多的。 我的主线程 以job 形式放入队列, 子线程 从队列内取出job.
执行完以后 放入结果队列,发消息。 这样就只要2个所。

论坛徽章:
0
发表于 2007-09-18 11:03 |显示全部楼层
如果只有一个线程读,一个线程写,那么不加锁绝对不危险。当然代码需要仔细斟酌,关键是更新指针的时机。

论坛徽章:
0
发表于 2007-09-18 13:20 |显示全部楼层
同意benjiam  (xxxx) 的意见,没看出来为什么需要那么多线程。我认为实际上如果任务处理时间很短的话甚至单线程也够用了。

如果只有一个线程读,一个线程写,那么不加锁绝对不危险。当然代码需要仔细斟酌,关键是更新指针的时机。

有一定道理,但我认为还是加锁比较简单、安全。因为正如你所说“当然代码需要仔细斟酌”。而且有个前提是对数据结构的修改可以在一个原子操作内完成。

只有线程调用了pthread_exit或者return,那么线程占用的资源就被释放了
pthread_join的作用是挂起当前的线程,等待另外一个线程结束。

这个观点是错误的。除非线程是detach的,否则它的资源需要pthread_join来回收。以下摘自man page
       When  a  joinable  thread  terminates,  its  memory  resources  (thread
       descriptor and stack) are not deallocated until another thread performs
       pthread_join on it. Therefore, pthread_join must  be  called  once  for
       each joinable thread created to avoid memory leaks.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP