有一个很多人也许都不是很清楚的问题:i++或++i是一个原子操作吗?在上一节,其实已经提到了,在SMP(对称多处理器)上,即使是单条递减汇编指令,其原子性也是不能保证的。那么在单处理机系统中呢?
Disruptor是LMAX公司开源的一个高效的内存无锁队列。这两天看了一下相关的设计文档和博客,下面尝试进行一下总结。 第一部分。引子 谈到并发程序设计,有几个概念是避免不了的。 1.锁:锁是用来做并发最简单的方式,当然其代价也是最高的。内核态的锁的时候需要操作系统进行一次上下文切换,等待锁的线程会被挂起直至锁释放。在上下文切换的时候,cpu之前缓存的指令和数据都将失效,对性能有很大的损失。用户态的锁虽然避免了这些问题,但是其实它们只是在没有真实的竞争时才有效。下面是一个计数实验中不加锁、使用锁、使用CA
关于无锁队列的实现,网上有很多文章,虽然本文可能和那些文章有所重复,但是我还是想以我自己的方式把这些文章中的重要的知识点串起来和大家讲一讲这个技术。下面开始正文。
Disruptor 是英国外汇交易公司 LMAX 开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题,因其出色的性能表现获得 2011 Duke’s 程序框架创新奖。
(1)队列的大小(m_lMaxQueueSize)应该足够的大,避免处理不过来时,找半天找不到空位置。
环形缓冲区支持队列管理。rte_ring并不是具有无限大小的链表,它具有如下属性:
Postgresql中的大锁很多,其中ProcArrayLock和XactSLRULock使用了无锁队列优化(PG中XID的分发也可以用这种机制优化,高压场景下效果不错)。
无锁队列适用场景: 两个线程之间的交互数据, 一个线程生产数据, 另外一个线程消费数据,效率高 缺点:需要使用固定分配的空间,不能动态增加/减少长度,存在空间浪费和无法扩展空间问题 package main import ( "fmt" "reflect" "strings" "time" ) type LoopQueue struct{ start int end int length i
我们清楚使用锁的性能比较低,尽量使用无锁设计。接下来就我们来认识下Disruptor。
作者:juliatliu,腾讯 PCG 运营开发工程师 一、无锁队列用在什么样的场景? 当需要处理的数据非常多,比如行情数据,一秒处理非常多的数据的时候,可以考虑用无锁队列。但是如果一秒只需要处理几百或者几千的数据,是没有必要考虑用无锁队列的。用互斥锁就能解决问题,数据量相对少的时候互斥锁与无锁队列之间差别并不是很明显。 二、为什么要用无锁队列? 有锁队列会有哪些问题? 1、Cache 的损坏,在线程间频繁切换的时候会导致 Cache 中数据的丢失; CPU 的运行速度比主存快 N 倍,所以大量的处理器时间
上一篇文章中,我们介绍了 Log4j2 异步日志的实现 -- AsyncAppender:
活锁、死锁本质上是一样的,原因是在获取临界区资源时,并发多个进程/线程声明资源占用(加锁)的顺序不一致,死锁是加不上就死等,活锁是加不上就放开已获得的资源重试,其实单机场景活锁不太常见。举个例子资源A和B,进程P1和P2,
1. 引言 现代计算机,即使很小的智能机亦或者平板电脑,都是一个多核(多CPU)处理设备,如何充分利用多核CPU资源,以达到单机性能的极大化成为我们码农进行软件开发的痛点和难点。在多核服务器中,采用多进程或多线程来并行处理任务,俨然成为了大家性能调优的标准解决方案。多进程(多线程)的并行编程方式,必然要面对共享数据的访问问题,如何并发、高效、安全地访问共享数据资源,成为并行编程的一个重点和难点。 传统的共享数据访问方式是采用同步原语(临界区、锁、条件变量等)来达到共享数据的安全访问,然而,同步恰恰和
最近一直在研究队列的一些问题,今天楼主要分享一个高性能的队列 Disruptor 。
最近常收到SOD框架的朋友报告的SOD的SQL日志功能报错:文件句柄丢失。经过分析得知,这些朋友使用SOD框架开发了访问量比较大的系统,由于忘记关闭SQL日志功能所以出现了很高频率的日志写入操作,从而偶然引起错误。后来我建议只记录出错的或者执行时间较长的SQL信息,暂时解决了此问题。但是作为一个热心造轮子的人,一定要看看能不能造一个更好的轮子出来。 前面说的错误原因已经很直白了,就是频繁的日志写入导致的,那么解决方案就是将多次写入操作合并成一次写入操作,并且采用异步写入方式。要保存多次操作的内容就要有一个类
最近常收到SOD框架的朋友报告的SOD的SQL日志功能报错:文件句柄丢失。经过分析得知,这些朋友使用SOD框架开发了访问量比较大的系统,由于忘记关闭SQL日志功能所以出现了很高频率的日志写入操作,从而偶然引起错误。后来我建议只记录出错的或者执行时间较长的SQL信息,暂时解决了此问题。但是作为一个热心造轮子的人,一定要看看能不能造一个更好的轮子出来。
说到无锁,其实就是用cas,不过我在百度上搜java实现无锁队列的文章其实不多,所以自己用cas和volatile实现一下,线程安全那是必须的。
/*是old_val, reg替换为new_val,返回为true;否则返回为false*/
开发过程中,对于多线程多进程的并发和并行的几乎是编程不可避免的事情,特别在涉及对于数据进行修改或者添加的时候。这个时候就需要锁的出现,锁有多种类型,互斥锁,自旋锁。除了锁之外,我们还定义了原子操作,当然如果探究本质的话,原子操作也是有锁的,只不过是对汇编的操作锁。
对比两脚本的执行结果,lock-free是明显优于spin-lock的。接着从程序代码的差异上分析,lock-free在一条语句上(atomic_compare_exchange_weak(&count, &val, val+1))完成了修改,而spin-lock则是“持有锁》修改值〉释放锁”。它们之间的差异可以由下两图体现:
RCU是Linux 2.6内核系统新的锁机制 RCU(Read-Copy Update)。参考:http://www.ibm.com/developerworks/cn/linux/l-rcu/
非池化/池化内存如何分配的?该撸这块了,奈何到处都在调用PlatformDependent类的方法,要不各种判断,要不分配堆外内存。反正到处都能看到它,得,索性先把这个撸一把。PlatformDependent又依赖了PlatformDependent0,那就一层一层剥好了。
也就常说的单生产者-单消费者 的ringbuffer, 限制就是只能一个读线程(消费者),一个写进程(生产者)。
一个程序员在没有成长成为架构师之前,几乎都要跟 Bug为伴,程序员有很多时间都是花在了查找各种 Bug上。
https://juejin.im/post/5b5f10d65188251ad06b78e3
曾经有个人,问我对无锁队列的实现是怎么想的。我想了一会儿,还是纳闷儿,无锁,也能做消息队列吗?然后他让我回去好好查查。没错,他就是面试官。
我们可以保证打印的global一定是2*20000000吗?答案是否定的。那为什么呢?
1.普通队列:先进先出。 2.带优先级的:(优先队列:本质上是二叉树)按照顺序进,出队列的时候出优先级最高的元素,如果优先级相同,再按照先进先出的方式。 3.带类型的:业务上的类型,与具体场景密切相关,入队列按照原来的顺序入,出队列按照类型取数据,相同类型元素再先进先出。 4.阻塞队列:线程安全版本队列(当队列为空,再去取元素就会发生阻塞;当队列为满,再去插入元素也会发生阻塞) 5.无锁队列:线程安全版本队列,不用管锁就能保证线程安全。
如何保证一个进程或线程能安全稳定地把一段消息发送到另一个进程和线程,甚至是另一台机器的进程或线程,再或是要通过代理转发到另一个进程或线程,一直是一个比较麻烦的问题。
听到队列相信大家对其并不陌生,在我们现实生活中队列随处可见,去超市结账,你会看见大家都会一排排的站得好好的,等待结账,为什么要站得一排排的,你想象一下大家都没有素质,一窝蜂的上去结账,不仅让这个超市崩溃,还会容易造成各种踩踏事件,当然这些事其实在我们现实中也是会经常发生。
队列是一种非常实用的数据结构,类似于生活中发排队,可应用于生活,开发中各个方面,比如共享打印机(先请求先打印),消息队列。你想知道他们是怎么工作的么。那就来一起学习一下队列吧
无锁编程,即通过CAS原子操作去控制线程的同步。如果你还不知道什么使CAS原子操作,建议先去查看相关资料,这一方面的资料网络上有很多。
最近Rust For Linux的项目,随着Rust的火爆也开始逐渐升温,但是谷歌的强烈支持以及rCore OS、Redox等各种Rust操作系统项目的经验积累,Rust想进入到Linux的真正核心,也还是有很长的路要走,之前笔者已经撰文对于Rust在汇编支持、panic和alloc等系统操作等方面的问题进行过简要说明了。这里再对于Rust进入到Linux内核的最大拦路虎-也就是内存模型方面的问题,做一下介绍。
numpy-ml 是一个使用 NumPy 实现的机器学习算法集合,尽管效率不高但相对易读。该项目的主要功能包括提供各种模型和工具函数来支持机器学习任务。
今天我们来研究学习一下AbstractQueuedSynchronizer类的相关原理,java.util.concurrent包中很多类都依赖于这个类所提供队列式同步器,比如说常用的ReentranLock,Semaphore和CountDownLatch等。
本文整理了Single Producer/Consumer lock free Queue step by step这篇文章里头关于高性能的SPSC无锁队列使用遵循的四个原则:
最近想解决下MyCat开统计后TPS吞吐量总上不去的问题,于是想起了Disruptor这个东西。之前想研究过,但是,由于当时并不太需要,而且感觉官方示例比较怪异,就是知道他比较快,没有想用。现在捡起来好好研究下。 首先,推荐大家并发编程网的Disruptor译文. 官网的翻译,翻译的不错,从硬件到软件,谈了Disruptor相对于传统阻塞队列的优化。这里主要针对源代码谈实现和应用。 首先,先拿一张图看一下Disruptor的主要元素:
转载自 https://blog.csdn.net/AJ1101/article/details/81711812
速度快的存储硬件成本高、容量小,速度慢的成本低、容量大。为了权衡成本和速度,计算机存储分了很多层次,扬长避短,有寄存器、L1 cache、L2 cache、L3 cache、主存(内存)和硬盘等。图1 展示了现代存储体系结构。
并发编程中,锁带解决了安全问题,同时也带来了性能问题,因为锁让并发处理变成了串行操作,所以如无必要,尽量不要显式使用锁。
1、面试跑不掉。现在只要面试Java相关的岗位,肯定或多或少会会涉及JDK源码相关的问题。
一、 引入 随着TIG阿基米德平台全面应用。组成京东容器生态技术栈的分布式域名解析服务ContainerDNS(go版https://github.com/tiglabs/containerdns )全量生产环境应用,承载着每天百亿的访问量,单实例峰值每秒请求达到15W QPS,已经接近ContainerDNS的性能极限(17W QPS)。为了更好的提高系统的并发服务,对ContainerDNS 的优化也势在必行。 本文对ContainerDNS性能优化思考和技术实践历程,希望对业内在容器领域和域名解析方
因个人开发需要音频处理,笔者在搜索相关工具时,发现了一个很新的实时音频 crate:basedrop,目前 github 星星数 20 左右。在对 basedrop 浅显实践后,感觉此 crate 非常棒,因此分享。
lock free (中文一般叫“无锁”,一般指的都是基于CAS指令的无锁技术) 是利用处理器的一些特殊的原子指令来避免传统并行设计中对锁(lock)的使用。
锁是高性能程序的杀手,但是为了保证数据的一致性,在多线程的应用环境下又不得不加锁。但是在某些特殊的场景下, 是可以通过优化数据结构来达到无锁的目的。那么我们就来看一下如何实现一个无锁队列。 队列:众所周知,就是先进先出。 出队列的时候从队列头取出一个结点;入队列的时候,将结点添加到队列尾部。当多线程同时操作一个队列读写时,显然就需要加锁。但是在单读单写的这种多线程应用时,是可以做到无锁的。直接上代码 #ifndef _QUEUE_H_ #define _QUEUE_H_ template<class T>
「CAS」(Compare And Swap) 是一种无锁算法的实现手段,中文名称为比较并交换。它由 CPU 的原子指令实现,可以在多线程环境下实现无锁的数据结构。
早在96年就有论文提出了无锁队列的概念,再到后来 Disruptor,高性能已得到生产的验证。此处介绍的 Jctools 中的高性能队列,其性能丝毫不输于 Disruptor。
领取专属 10元无门槛券
手把手带您无忧上云