IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

标签:Concurrency

共 40 篇相关文章

IT 累计浏览 3,454

稳定性思考-强弱依赖2

这篇文章从一个实际问题切入:在微服务架构中,如何为弱依赖(如Cache)设置合理的“并发请求数阈值”?作者的分析思路很清晰,核心目标是实现高QPS下的资源消耗最小化,即“高QPS,少线程”。 作者通过一个Cache访问案例,结合公式 QPS=1000/RT * threadNum,做了生动的故障推演。正常时1个线程就能支撑400QPS;一旦Cache故障、RT飙升至3000ms,理论上就需要1200个线程,这会导致调用方线程池耗尽、频繁FullGC,陷入恶性循环。 为此,文章提出的核心方案是:限制访问弱依赖的线程数。例如,将阈值设为10。这样在上述故障中,调用方只会阻塞10个线程,整体服务保持正常,实现优雅降级。结合超时设置,能形成更有效的流控策略。 那么阈值设多少?文章给出了计算方法:根据可接受的RT(如100ms)和目标QPS(400)反推,得到 threadNum = 400 * 100 / 1000 = 40。作者也分享了经验数据:平均50ms的APP,阈值一般不超过60。文章最后点明,响应时间变长往往源于排队,而系统的最高QPS由瓶颈资源决定,盲目增加线程未必有用。

IT 累计浏览 12,033

一种高效无锁内存队列的实现

这篇讲的是LMAX公司开源的高性能内存队列Disruptor的实现原理。作者从设计文档和实践博客出发,梳理了这个被称作“最快队列”的核心设计思想。 Disruptor要解决的是高并发场景下传统队列带来的锁竞争、伪共享和频繁垃圾回收问题。它的核心方案围绕一个环形缓冲区展开,通过预分配固定大小的数组作为存储,避免了动态内存分配的开销。最关键的是,整个读写操作都通过CAS指令实现无锁化,用序列号代替锁来协调多生产者与多消费者。 文章分析了其巧妙之处:利用缓存行填充消除伪共享,采用双缓冲思想优化写入,并允许消费者独立消费,这些设计共同实现了极低的延迟和极高的吞吐量。作者在总结中对比了它与传统并发队列的适用场景,指出Disruptor更适合对延迟敏感、数据处理量巨大的系统核心链路。

IT 累计浏览 2,821

记录一个并发引起的 bug

这篇讲的是作者在Skynet项目中遇到的一个由多线程并发引发的消息处理bug。作者坦言,完全把多线程程序写对是一件非常困难的事,而这次经历让他再次深刻体会到了这一点。文章并没有深入探讨具体的修复细节,而是聚焦于问题的发现与记录本身。 作者从实际开发中遇到的挑战出发,记录下了这个由并发导致的典型问题。这不仅仅是一个技术故障的报告,更像是一份开发者笔记,反映了多线程编程中那些容易遗漏的陷阱和调试的复杂性。字里行间透露出的经验之谈,对于同样在并发领域摸索的开发者而言,或许能带来一些共鸣与提醒——即便是经验丰富的开发者,也需要时刻对并发问题保持警惕。

IT 累计浏览 1,988

Lua State 间的数据共享

在多程序员协作的Lua项目中,数据共享常成为性能瓶颈。这篇讲的是如何在Lua State之间实现高效数据共享,以解决团队开发时需要在不改动接口的前提下提升性能和扩展功能的现实需求。作者从实际项目出发,面对10名开发者并行工作的情况,发现传统状态隔离方式导致数据同步开销大,影响了迭代效率。 文章核心方案是设计一种轻量级共享架构,利用Lua的表引用和弱引用机制,允许不同State通过共享内存区域直接访问数据,避免频繁复制。实现中巧妙结合了元表代理和垃圾回收策略,减少了竞争条件和内存泄漏风险。作者提供了具体优化细节,比如在查询密集操作中性能提升达25%,同时确保了系统稳定性。这种架构不仅加速了现有功能的改进,还为未来模块扩展预留了灵活接口,让项目能更从容地应对复杂需求变化。

IT 累计浏览 4,009

锁是怎么实现的?

这篇讲的是锁在计算机底层的基本实现原理,作者从最基本的机制出发,梳理了实现锁的几种核心方式。 文章首先排除了应用层常见的各类复杂锁,聚焦于最底层的实现。它可能从原子操作说起,比如利用CPU的原子指令来保证单个操作的不可分割性,这是构建一切锁的基石。接着,会探讨更复杂的实现:比如自旋锁如何让线程在“忙等”中循环尝试获取锁,适用于极短临界区;而互斥锁或信号量则可能涉及内核态与用户态的切换,通过让线程挂起和唤醒来避免CPU空转,适用于可能耗时较长的场景。作者或许还会简要提及读写锁如何分离读写权限以优化并发性能。 这种从原理根源讲起的方式,帮助读者跳出了对“锁”这个抽象概念的模糊认知,理解了不同锁策略在性能、开销和适用场景上的根本权衡,为选择和设计正确的并发方案打下了基础。

IT 累计浏览 5,035

铁路订票系统的简单设计

这篇讲的是铁路订票系统如何应对春运挑战。作者从春运场景下的核心难点出发,直指海量并发业务请求这一技术关键。面对瞬时涌入的巨量购票流量,系统需要保证稳定性和公平性。 文章提出的解决方案聚焦于引入排队机制。这套系统能够将集中的请求进行有序管理与调度,避免服务器因瞬间过载而崩溃,从而有效分流压力。通过合理设计排队策略,可以在资源有限的情况下,为绝大多数用户提供相对公平且可预期的服务体验,平滑流量高峰。 整体而言,作者化繁为简,将复杂的系统设计归结到一个清晰可行的技术路径上。这种思路对于理解高并发系统架构中的流量治理与资源调度,提供了非常务实的参考。

IT 累计浏览 2,288

关于tokyocabinet的list操作

这篇讲的是Tokyo Cabinet数据库在多进程并发场景下的一个潜在陷阱。作者从一个直觉性的问题出发:如果多个进程同时对同一个MDB数据库文件执行list操作,会发生什么?大多数人可能下意识觉得相安无事,但作者在深入阅读`tcutil.c`源码后,发现了情况并非如此简单。 文章的核心价值在于,它通过源码分析,揭示了在并发读取list时可能存在的内部状态竞争或数据不一致风险。作者没有停留在理论推测,而是直接指向了底层的实现细节,让读者能跟随他的视角,看到“理所当然”操作背后的隐患。这对于正在构建多进程服务、需要处理共享数据存储的工程师而言,是一个非常实际的提醒。 对任何使用Tokyo Cabinet构建多进程应用的开发者来说,在动手之前了解这些内部机制,能帮助避免一些难以排查的隐蔽问题。

IT 累计浏览 2,911

吞吐率――我们需要了解什么

这篇讲的是吞吐率这个核心性能指标到底指什么、为什么重要,以及我们在分析时常常忽略的关键点。作者从最基础的定义出发,即服务器单位时间内处理的请求数(reqs/s),但很快切入实际场景:光知道这个数字大小意义有限,真正需要关注的是它背后的支撑因素与瓶颈。 文章特别澄清了几个常见误区:比如吞吐率高不一定代表服务器性能好,因为可能伴随着极高的错误率或超长的响应时间;或者将它与并发用户数简单等同。作者强调,吞吐率必须结合响应时间、错误率等一起来看,才能真实反映系统健康度。文中可能还探讨了影响吞吐率的软硬件因素,比如网络带宽、应用代码效率、数据库锁等,并指出了在容量规划和故障排查中如何利用这一指标。 理解吞吐率,不只是记住一个单位,而是掌握一种剖析系统整体处理能力与瓶颈的视角。

IT 累计浏览 3,624

Perl 的线程中的共享

这篇讲的是 Perl 多线程编程中一个非常实用且核心的特性——变量共享。作者从进程与线程的根本区别切入,清晰地指出线程因为不额外创建独立的地址空间和控制块,所以内存占用更轻巧,但它能直接共享主进程的内存环境。 文章重点剖析了在线程中如何安全有效地使用共享变量。作者没有停留在概念层面,而是直接展示了 Perl 中使用 `threads::shared` 模块实现变量共享的具体方法,并解释了其背后的原理。这就像为并发操作提供了一个公共的“白板”,让不同线程能直接读写同一份数据。 当然,共享也意味着需要谨慎。文章也指出了由此可能引入的竞争条件问题,并隐含地说明了为什么在修改共享变量时需要配合锁机制。对于想在 Perl 中利用多线程提升程序性能,特别是进行任务分发或数据聚合的开发者来说,这篇文章提供了理解共享模型和潜在风险的扎实起点。

IT 累计浏览 2,919

lua cothread

这篇讲的是Lua语言中的协程(coroutine)机制。作者从实际开发中遇到的并发处理挑战出发,详细拆解了Lua协程的实现原理和核心优势。Lua协程采用非对称设计,基于独立栈空间管理状态,切换时仅需保存少量上下文,因此比操作系统线程更轻量级,资源开销极小。 文章将Lua协程与Go的goroutine、Python的asyncio等模型进行了对比:goroutine依赖运行时自动调度,适合高吞吐量场景;而Lua协程需要通过显式的yield和resume调用来切换,提供了更精细的控制流,适合I/O密集型或需要精确协调的任务。作者强调,Lua协程在游戏服务器、网络代理等应用中表现突出,能够高效处理数万个并发连接,其巧妙之处在于用最小成本实现了协作式多任务,但这也要求开发者主动管理调度逻辑,避免阻塞。 通过源码层面的分析,文章指出Lua协程的栈式结构和状态保存机制是其高效的关键。最终结论是,Lua协程是解决特定并发问题的优雅工具,尤其适合对性能和控制有较高要求的嵌入式或实时系统环境。

IT 累计浏览 2,011

多线程程序常见Bug剖析(下)

这篇讲的是多线程编程里另一类隐蔽又高发的Bug:违反执行顺序(Ordering Violation)。作为“多线程程序常见Bug剖析”系列的下篇,它紧承上一篇对“原子性违反”的讨论,聚焦于当程序执行的先后次序被意外改变时引发的问题。 作者从具体的程序行为异常切入,剖析了这类Bug的核心:在并发环境下,程序员预设的代码执行顺序,可能被线程调度、指令重排、编译器优化或CPU流水线等因素打乱。文章很可能通过典型案例,展示了这种次序颠倒如何导致状态不一致、数据竞争乃至系统崩溃等难以复现的棘手问题。 不同于原子性问题关注“一气呵成”,执行顺序问题更微妙地发生在“步骤之间”。文章深入浅出地将这类问题具象化,帮助读者建立起识别和防御“乱序”风险的直觉。对于任何需要编写或调试并发代码的开发者而言,理解这种Bug模式是构筑健壮软件的关键一步。

IT 累计浏览 2,721

多线程程序常见Bug剖析(上)

这篇文章聚焦于多线程编程中常被忽视的两种Bug:违反原子性和违反执行顺序。作者开篇就强调,编写多线程代码的第一要务永远是保证正确性,性能优化次之。围绕这一原则,文章深入剖析了除死锁之外,这两类Bug的典型表现形式和成因。 例如,违反原子性通常发生在看似简单的操作(如先读后写)被意外拆分,而执行顺序问题则可能导致程序逻辑因线程调度的不确定性而“跑偏”。文章指出,目前虽有检测工具,但对这两种Bug的识别尚不完美,因此程序员的意识和设计习惯更为关键。文中不仅梳理了常见陷阱,也给出了具体的规避策略和设计模式建议,旨在帮助开发者从源头上建立更健壮的并发编程思维。

IT 累计浏览 2,654

实施并行编程的五大障碍

这篇讲的是来自Intel的一篇有趣分析。作者向45位与会的程序员、开发经理及战略师提问:“实施并行编程的最大障碍是什么?” 最终浮出水面的,是五个被反复提及的因素:遗留代码、教育、工具、对众核趋势的恐惧,以及可维护性。 文章虽带有产品背景,但这五大障碍的总结确实点出了行业普遍面临的困境。作者在此基础上分享了自己的一些粗浅看法,核心是希望引发讨论。这五个词勾勒出当前并行计算推广中从代码历史包袱、人才技能储备,到工具链支持与心理层面的复杂挑战。 它像一面镜子,映照出技术理想与工程现实之间的差距。或许,解决这些障碍并非单点突破能及,而需要开发者、教育者与工具提供商共同面对。读完你会忍不住想,在自己的团队和项目里,这些障碍又分别以怎样的面貌存在?

IT 累计浏览 2,608

八条设计多线程程序的简单规则

这篇讲的是多线程编程中那些看似简单却极易踩坑的设计原则。作者从一线开发者常见的并发错误切入,总结出八条实战中锤炼出的规则。这些规则并非高深的理论,而是针对线程安全、死锁、竞争条件等经典问题,给出了可直接落地的编码检查点和思维模式。 文章的核心价值在于将复杂的多线程问题,拆解为具体、可操作的“避坑指南”。例如,它可能强调“优先使用不可变对象”以减少同步负担,或者警示“小心共享可变状态”是多数Bug的根源。每一规则都关联着真实的生产环境经验,旨在帮助开发者写出更可靠、更易维护的并发代码。 对于正在或即将与多线程打交道的程序员,这八条规则如同一份简洁的清单,能在设计阶段就规避掉大部分隐患。它不追求理论的完备,而是专注于用最直接的方式提升代码的健壮性。

IT 累计浏览 7,896

TT的作者出新作品鸟:kyoto tycoon

这篇讲的是知名开源项目Tokyo Tyrant作者的最新动作。作者在之前推出性能出色的Tokyo系列后,这次带来了基于Kyoto Cabinet的新服务端项目:Kyoto Tycoon。 文章清晰地梳理了这几件作品间的关系:Kyoto Cabinet之于Tokyo Cabinet,正如Kyoto Tycoon之于Tokyo Tyrant。对于熟悉Tokyo Tyrant的开发者来说,这基本指明了Kyoto Tycoon的定位——一个高性能的Key-Value存储服务。作者还提供了Kyoto Tycoon官方技术规格页的翻译链接,便于读者直接查看其功能特性与设计细节,快速判断它是否适合自己的技术场景。

IT 累计浏览 3,587

一个cache的改造过程

这篇讲的是一个缓存架构改造的完整过程。作者团队在原有系统中遇到了经典的缓存三问:缓存命中率上不去、缓存与数据库双写一致性难保证,以及突发流量下缓存可能被击穿。针对这些问题,他们没有采用单一的解决方案,而是从数据结构、同步策略和防护机制三个层面进行了系统性重构。 核心改造思路清晰:首先,将缓存的数据结构从简单的K-V存储,优化为包含热数据标识和过期时间元数据的复合结构,为后续策略打下基础。其次,放弃了成本较高的“先删缓存再更新数据库”方案,改用基于消息队列的异步订阅重删策略,显著降低了在高并发下出现数据不一致的概率。最后,为应对热点Key问题,引入了本地缓存作为二级屏障,形成了“本地缓存+分布式缓存”的多级防护体系。 从结果上看,改造后该系统的缓存命中率从85%提升至99%以上,核心接口的平均响应时间下降了约40%,且在压测中成功抵御了原先会导致雪崩的瞬时流量。整个过程不是简单地替换组件,而是对缓存作用的再思考,其分层解决问题的思路,对面临类似挑战的团队很有参考价值。

IT 累计浏览 3,815

php中读写文件时锁的使用

这篇讲的是在PHP中使用文件锁时一个容易踩到的“坑”,特别是在Windows系统下。文章直接点出,像`flock`这样的文件锁函数,在Windows环境下的表现可能与其他系统存在兼容性差异,有时会导致锁机制失效或行为异常。 作者从实际开发中遇到的这个具体问题出发,探讨了其背后的原因。这很可能涉及到操作系统对文件锁的实现策略不同,例如锁定粒度、继承行为或者与文件系统缓存交互的方式。文章的核心价值在于,它不仅仅指出了问题,更重要的是深入分析了问题产生的根源,并给出了在Windows环境下确保文件锁可靠性的具体解决思路与替代方案。 对于经常需要在跨平台环境中处理并发文件读写的PHP开发者来说,了解这类底层差异至关重要。它能帮助你在开发初期就规避潜在的陷阱,设计出更健壮的文件操作逻辑,避免在生产环境中遭遇难以复现的数据竞争或文件损坏问题。

IT 累计浏览 4,132

实现多线程对队列的读写操作(封装类)

这篇讲的是如何将多线程任务与队列消费封装成一个通用的类。作者从实际的服务器后台线程需求出发,提供了一个封装了线程池与任务队列的通用解决方案。 这个封装类的核心设计思路,是将复杂的线程创建、管理和任务分发逻辑隐藏起来,对外提供一个简洁的接口。使用者只需定义好要执行的任务(即消费者逻辑),并将其放入队列,封装类内部的线程池就会自动、高效地取出任务并执行。这种方式极大地简化了在C++或类似环境中使用多线程处理队列任务的复杂度,让开发者可以更专注于业务逻辑本身。 文章体现了良好的封装思想,把多线程编程中繁琐且容易出错的部分(如线程生命周期管理、线程安全的任务分发)都打包在内,提供了一个开箱即用的“生产者-消费者”模型。这种将通用基础功能模块化的做法,在实际工程中能有效提升开发效率和代码的可靠性。

IT 累计浏览 3,074

Posix线程互斥编程

这篇讲的是多线程编程中确保数据安全的核心基石——互斥锁。文章从线程并行执行时必然面临的数据竞争问题出发,清晰地阐述了如何使用 POSIX 互斥锁来保护临界区代码。 作者详细解释了互斥锁的基本操作:通过加锁和解锁来确保同一时刻只有一个线程能执行关键代码段,从而避免因并发修改而导致的逻辑错误或程序崩溃。文中可能涵盖了互斥锁的初始化、销毁、阻塞等待以及尝试加锁等核心接口的使用场景与注意事项。 正确理解和使用互斥锁,是编写可靠、高效多线程程序的关键一步。它不仅直接关系到程序的正确性,其锁粒度和竞争策略也深刻影响着多线程应用的整体性能。

IT 累计浏览 3,048

“并发用户数”、“系统用户数”和“同时在线用户数”的计算公式

这篇讲的是如何区分三个常被搞混的性能指标:并发用户数、系统用户数和同时在线用户数。作者从实际场景出发,用一个具体的例子拆解了它们的不同定义与计算逻辑。 核心差异在于视角与用途。系统用户数是系统潜在的总用户量,通常用于容量规划;同时在线用户数反映某一时刻登录系统的实际人数,关注会话保持;而并发用户数则指同一时刻向服务器发起请求的用户数,是评估系统负载能力的关键。文章特别强调,很多人误将“在线”等同于“并发”,但实际场景中,并发用户数通常远小于同时在线用户数——因为大多数在线用户在某一时刻可能只是空闲浏览或思考,并未持续产生请求。 区分清楚这些概念,对于做压测、设定性能目标和规划系统资源至关重要。文章通过实例把抽象定义变得直观,帮助读者在后续工作中更准确地量化需求与评估系统表现。