ascs 简明开发教程(十九):到底什么情况下才能使用无锁队列缓存

31 篇文章 0 订阅
31 篇文章 1 订阅

QQ交流群:198941541

无锁队列即non_lock_queue,只要你用的container(队列用到的容器,默认是list,非线程安全,队列只是包装容器的接口而已,类似于双端队列,栈队列等)是线程安全的,就一定可以用无锁队列。我们重点要讲的是,如果container非线程安全,哪种类型的业务可以用无锁队列(file_server就用了无锁发送缓存队列)。

先说说socket里面到底有多少线程,service线程可以开很多,但是由于用了asio的strand,它可以保证不并发,所以我们仍然把这种情况看成单线程(虽然线程id不一样),基于这样的前提,每一个socket里面,都有两条线程,一是收发线程(收发需要互斥,有点奇怪,但asio就是这么设计的,它的socket是非线程安全的,好在只是异步收发调用时需要互斥,真正的异步数据收发并不需要),on_msg_send,on_all_msg_send,on_msg(同步批量派发)工作在这个线程里面;一是消息派发线程,on_msg_handle(异步批量派发),on_msg_handle(异步单条消息派发)工作在这个线程里面。

只要你只在上面说的两个线程中的一个里面操作收/发缓存队列(且ascs不会在另外一个线程里面也操作它,具体怎么判断由业务决定,请往下看),就可以用无锁队列且不需要container是线程安全的。这个结论说起来容易,一到实际使场景还是会懵,所以我们举实际案例来case by case的分析。

一:乒乓测试,如果两端都一直把收到的消息发回去(concurrent_client + concurrent_server就是这样的),假如从客户端开始,那么除了第一个消息,其它消息都是在on_msg或者on_msg_handle里面发送的,看起来可以使用无锁队列,实际上要分两种情况,如果采用同步批量派发(on_msg),的确是可以使用无锁发送缓存队列,前提是你必须在on_msg里面处理完所有消息(因为不处理完的消息会走异步派发模式),对于接收缓存队列,因为完全没使用,所以使不使用无锁队列并没有区别;如果采用异步派发(on_msg_handle),则肯定是不能使用无锁发送缓存队列了,因为在收发线程和消息派发线程里面都会访问发送缓存队列(其中在收发线程的访问是ascs做的),那接收缓存队列可以使用无锁队列吗?答案是不能,因为收发线程和消息派发线程里面都会访问接收缓存队列(均是由ascs做的),这已经与你的业务无关了,是ascs的设计,所以请记住,只要用异步消息派发,接收缓存队列就不能用无锁的了,再广泛一点,如果你的container非线程安全,接收缓存队列就不要再考虑无锁队列了,因为虽然同步派(处理完消息)可以无锁,但也用不上接收缓存队列了,此时有锁和无锁并没有区别

二:file_server,它用的是异步消息派发,所以接收缓存队列肯定不能是无锁的了。对于消息发送,分两个阶段,第一阶段是协商阶段(client请求文件,server返回文件大小,然后client请求从文件指定的偏移处的指定长度的数据,server进入第二阶段),第二阶段是数据发送阶段(流式无协议)。对于第一阶段,server只会回一个消息,回这个消息之前是idle状态,即不可能有消息正在发送,那么这个消息虽然是在消息派发线程里面发的,但由于在收发线程里面不可能有消息发送,所以仍然是安全;对于第二阶段,消息的发送会一直在收发线程里面(on_msg_send,与ascs访问发送队列互斥),所以也是安全的;综上,file_server采用了无锁发送队列缓存。

三:file_client,它用的是异步消息派发,所以接收缓存队列肯定不能是无锁的了。对于消息发送,它只有第一阶段,是在消息派发线程和主线程里面做的,且总共需要发送2个消息,那就不安全了(因为在消息派发线程和收发线程里面均访问了发送缓存队列,无法互斥),而且主线程还能发送talk消息,也是不安全的,所以file_client不能采用无锁发送队列缓存。

四:我只在一个线程里面发送数据,但这个线程不是service线程,这种情况下也是不能用无锁队列的,即使你用safe_send_msg也不行,因为收发线程也会访问发送缓存队列,消息发送是异步的,它不与你调用的send_msg一一对应,send_msg只是把消息放到发送缓存队列而已,如果一个send_msg对应一个async_write,那就会出现并发的异步发送,这样消息会乱序,其次是这样缓存占用也不可控。

上一篇 ascs 简明开发教程(18) 下一篇 ascs 简明开发教程(20)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值