libevent学习笔记十三:让libevent支持多线程

 libevent学习笔记十三:让libevent支持多线程

      Libevent本身不是多线程安全的,在多核的时代,为了充分利用CPU的计算能力,在多线程环境中使用libevent,跟源代码的关系关系不大,纯粹是使用上的技巧。

1、错误使用示例

     在多核的CPU上只使用一个线程,绝对是浪费CPU的处理能力,暴煁天物,必须多创建几个线程,比如下面的简单服务器场景

     1)主线程创建工作线程1(主线程);
     2)接着主线程监听在端口上,等待新的连接;
     3)在线程1(主线程)中执行event事件循环,等待事件到来;
     4)新连接到来,主线程调用libevent接口event_add将新连接注册到libevent上;

     上面的逻辑看起来没什么问题,在很多服务器设计中都可能用到主线程和工作线程的模式….。可是就在线程1注册事件时,主线程很可能也在操作事件,比如删除、修改,通过libevent的源代码也能看到,没有同步保护机制,会出现严重的问题,下面对多线程的模式进行说明。

2、支持多线程的几种模式

    Libevent并不是线程安全的,但这不代表libevent不支持多线程模式,其实方法在前面已经将signal事件处理时就接触到了,那就是消息通知机制。就是这种模式:“有消息通知我,然后再在合适的时间来处理”;用一个形象的比喻来描述这个场景:就像一个项目组,每个成员都是一个成员,作为一个工作线程,项目组长是主线程,成员接受组长的指令指派接受的任务,就是工作线程接受主线程的消息来执行任务。

    可能的发生的模式有以下几个方式:

2.1 暴力抢占模式 

    这个场景是在多线程模式下,相当下面的流程:
     1) 当时你正在做事,比如在编写代码、写文档等;
     2)组长找到某个成员分配了一个任务,要指派组员,比如临时写个汇报PPT等;
     3)组长命令某个组员马上搞PPT,这时这个成员不得不停止手头的工作,把PPT搞定了再接着写文档或开发代码;

2.2 纯粹的消息通知机制模式

那么基于纯粹的消息通知机制的多线程方式就像下面这样:
     1)当时某个组员正在写文档、开发代码;
     2)项目组长有一个任务,找到某个组员,要指派给他,临时写一个汇报的PPT;
     3)组长发个指令消息到给某个组员,有个写PPT要安排给他,这时组员并没立即处理;
     4)这个组员仍然继续于哪里的开发代码、写文档的工作,完成后,接着响应组长这个PPT任务,开始执行PPT的任务;

       2.1的场景的好处是消息可以立即得到处理,但是很方法很野蛮粗暴,必须立即处理这个消息,所以组员必须处理好切换问题,省得把文档上的内容不小心写到PPT里。在操作系统的进程通信中,消息队列(消息信箱)都是操作系统维护的,不必关心。
      2.2的场景优点是通过消息通知,切换问题省心了,不过消息是不能立即处理的(基于消息通知机制,这个总是难免的),而且所有的内容都通过消息发送,比如PPT的格式、内容等等信息,这无疑增加了通信开销。

2.3 消息通知+同步层

     有个折中机制可以减少消息通信的开销,就是提取一个同步层,还拿上面的例子来说,你把工作安排都存放在一个工作队列中,而且你能够保证“任何人把新任务扔到这个队列”,“自己取出当前第一个任务”等这些操作都能够保证不会把队列搞乱(其实就是个加锁的队列容器)。
    再来看看处理过程和上面有什么不同:
     1)当时某个成员正在写文档;
     2)项目组长找到了某个项目成员,有一个任务,要指派给他,要他临时写一个项目汇报的PPT;
     3)项目组长有个PPT要某个项目成员搞定,组长把任务push到某个项目成员的工作队列中,包括了PPT的格式、内容等信息;
     4)项目组长发个消息(一个字节)到某个项目成员信箱,有个PPT要他搞定,这时某个项目成员并不马上响应组长;
     5)该组员写好文档,发现有新消息(这预示着有新任务来了),检查工作队列知道头有个PPT要他搞定,该组员开始搞PPT;

        工作队列其实就是一个加锁的容器(队列、链表等等),这个实现起来很容易;而消息通知仅需要一个字节,具体的任务都push到了在工作队列中,因此想比2.2减少了不少通信开销。
      多线程编程有很多陷阱,线程间资源的同步互斥不是简单的描述能说得清的,而且出现bug很难跟踪调试;如果要了解这些,可以参见本人的博客,关于内核核心编程的内容介绍。在本文的三种方法中,选择机制3作为实现多线程的方法更为合理些。

3、例子——memcached

      Memcached中的网络部分就是基于libevent完成的,其中的多线程模型就是典型的消息通知+同步层机制。下面的图说明其多线程模型了,其中有详细的文字说明。

4、总结

     本节描述的是libevent的使用多线程等方面的技巧,讨论了一下如何让libevent支持多线程,以及几种支持多线程的机制,和memcached开发的实例使用libevent的多线程模型

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
libevent是一个事件驱动的网络库,用于开发高效的网络应用程序。它支持多线程编程,但是在使用libevent多线程模式时需要注意一些问题。首先,libevent的信号事件是不支持多线程的,因为它使用了全局变量。这意味着在多线程环境下,注册信号事件可能会导致竞争条件和错误的结果。这一点可以在中的文章中找到更详细的解释。为了避免这个问题,可以考虑使用其他方式处理信号事件。 另外,在多线程模式下,主线程和工作线程之间可能存在并发操作事件的问题。当一个线程注册事件时,另一个线程可能同时在操作事件,比如删除或修改事件。libevent的源代码中没有提供同步保护机制,这可能导致严重的问题。因此,在多线程模式下使用libevent时,需要谨慎处理事件的操作,确保线程安全。这一点可以在中的文章中找到更详细的说明。 总结来说,libevent支持多线程编程,但需要注意信号事件不支持多线程,并且需要处理并发操作事件的问题。在使用libevent多线程模式时,建议仔细阅读相关文档和源代码,确保线程安全性。123 #### 引用[.reference_title] - *1* *2* [libevent多线程](https://blog.csdn.net/zhbt1234/article/details/53782589)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}} ] [.reference_item] - *3* [libevent学习笔记十三:让libevent支持多线程](https://blog.csdn.net/jyl_sh/article/details/105895355)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jyl_sh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值