性能优化-使用双buffer实现无锁队列

本文探讨了在多线程环境下,如何通过双buffer策略优化性能,实现一写多读的无锁操作。文章介绍了背景、现有方案的不足以及优化思路,详细阐述了如何使用智能指针确保读写互斥,最后提到了双buffer方案的局限性和内存浪费问题。
摘要由CSDN通过智能技术生成

在我们的工作中,多线程编程是一件太稀松平常的事。在多线程环境下操作一个变量或者一块缓存,如果不对其操作加以限制,轻则变量值或者缓存内容不符合预期,重则会产生异常,导致进程崩溃。为了解决这个问题,操作系统提供了锁、信号量以及条件变量等几种线程同步机制供我们使用。如果每次操作都使用上述机制,在某些条件下(系统调用在很多情况下不会陷入内核),系统调用会陷入内核从而导致上下文切换,这样就会对我们的程序性能造成影响。

今天,借助此文,分享一下去年引擎优化的一个点,最终优化结果就是在多线程环境下访问某个变量,实现了无锁(lock-free)操作。

背景

对于后端开发者来说,服务稳定性第一,性能第二,二者相辅相成,缺一不可。

作为IT开发人员,秉承着一句话:只要程序正常运行,就不要随便动。所以程序优化就一直被搁置,因为没有压力,所以就没有动力嘛😁。在去年的时候,随着广告订单数量越来越多,导致服务rt上涨,光报警邮件每天都能收到上百封,于是痛定思痛,决定优化一版。

秉承小步快跑的理念,决定从各个角度逐步优化,从简单到困难,逐个击破。所以在分析了代码之后,准备从锁这个角度入手,看看能否进行优化。

在进行具体的问题分析以及优化之前,先看下现有召回引擎的实现方案,后面的方案是针对现有方案的优化。

  • 广告订单以HTTP方式推送给消息系统
  • 消息系统收到广告订单消息后
    • 将广告订单消息格式化后推送给消息队列kafka(第1步)
    • 将广告订单消息持久化到DB(第2步)
  • 召回引擎订阅kafka的topic
    • 从kafka中实时获取广告订单消息,建立并实时更建立维度索引(第3步)
    • 召回引擎接收pv流量,实时计算,并返回满足定向后的广告候选集(第4步)

从上面图中可以看出,召回引擎是一个多线程应用,一方面有个线程专门从kafka中获取最新的广告订单消息建立维度索引(此为写线程),另一方面,接收线上流量,根据流量属性,获取广告候选集(此为读线程)。因为召回引擎涉及到同时读和写同一块变量,因此读写不能同时操作。

概述

在多线程环境下,对同一个变量访问,大致分为以下几种情况:

  • 多个线程同时读
  • 多个线程同时写
  • 一个线程写,一个线程读
  • 一个线程写,多个线程读
  • 多个线程写,一个线程读
  • 多个线程写,多个线程读

在上述几种情况中,多个线程同时读显然是线程安全的,而对于其他几种情况,则需要保证其_互斥排他_性,即读写不能同时进行,管他几个线程读几个线程写,代码走起。


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值