精华内容
下载资源
问答
  • 并发算法

    2018-10-14 19:51:48
    计算机科学中,并发算法就是可以在并发情况下执行的算法。大多数计算机算法都是顺序算法,并且假设该算法从开始运行到结束,不需要执行其他任何进程。这些算法在并发情况下通常无法正确运行,并且结果不确定,因为...

    计算机科学中,并发算法就是可以在并发情况下执行的算法。大多数计算机算法都是顺序算法,并且假设该算法从开始运行到结束,不需要执行其他任何进程。这些算法在并发情况下通常无法正确运行,并且结果不确定,因为实际的计算过程是由外部调度程序决定的。并发通常会为算法增加复杂度,并且需要并发控制,例如使用互斥锁避免竞争条件之类的问题。

    许多并行算法可以并发运行,特别是分布式算法,尽管它们在概念上截然不同。


    翻译源:维基百科

    展开全文
  • 文本通过实例比较了各种基于锁的并发算法和无锁并发算法的性能:系 http://mechanical-sympathy.blogspot.com/2013/08/lock-based-vs-lock-free-concurrent.html 文翻译    上周在由Heinz Kabutz通过JCrete ...

    文本通过实例比较了各种基于锁的并发算法和无锁并发算法的性能:系 http://mechanical-sympathy.blogspot.com/2013/08/lock-based-vs-lock-free-concurrent.html  文翻译

     

          上周在由Heinz Kabutz通过JCrete 组织的开放空间会议(unconference)上,我参加一个新的java规范 JSR166 StampedLock的审查会议。StampedLock 是为了解决多个readers 并发访问共享状态时,系统出现的地址竞争问题。在设计上通过使用乐观的读操作,StampedLock 比ReentrantReadWriteLock 更加高效;

     

          在会议期间,我突然意思到两点:第一、我想是时候该去回顾java中锁的实现的现状;第二、虽然StampedLock 看上去是JDK很好的补充,但是它视乎忽略了一个事实,即在多个reader的场景里,无锁的算法通常是更好的解决方案。

     测试:

          为了比较不同的实现方式,我需要采用一种不偏向任意一方的API测试用例。 比如:API必须不产生垃圾、并且允许方法是原子性的。一个简单的测试用例是设计一个可在两维空间中移动其位置的太空船,它位置的坐标可以原子性的读取;每一次事物里至少需要读写2个域,这使得并发变得非常有趣;

      

    /**
     * 并发接口,表示太空船可以在2维的空间中移动位置;并且同时更新读取位置
     */
    public interface Spaceship
    {
        /**
         *  读取太空船的位置到参数数组 coordinates 中
         *
         * @param coordinates 保存读取到的XY坐标.
         * @return 当前的状态
         */
        int readPosition(final int[] coordinates);
     
        /**
         *  通过增加XY的值表示移动太空船的位置。
         *
         * @param xDelta x坐标轴上移动的增量.
         * @param yDelta y坐标轴上移动的增量.
         * @return the number of attempts made to write the new coordinates.
         */
        int move(final int xDelta, final int yDelta);
    }

     

          上面的API通过分解一个不变的位置对象,本身是干净的 。但是我想保证它不产生垃圾,并且需要能最直接的更新多个内容域。这个API可以很容易地扩展到三维空间,并实现原子性要求。

     

          为每一个飞船都设置多个实现,并且作为一个测试套件。本文中所有的代码和结果都可以在这里找到。

     

          该测试套件会依次运行每一种实现.并且使用 megamorphic dispatch模式,防止并发访问中的方法内联(inlining),锁粗化(lock-coarsening),循环展开( loop unrolling)的问题;

     

           每种实现都执行下面4个不同的线程的情况,结果也是不同的;

          1 reader - 1 writer

          2 readers - 1 writer

          3 readers - 1 writer

          2 readers - 2 writers

     

          所有的测试运行在64位机器、Java版本:1.7.0_25、 Linux版本:3.6.30、4核 2.2GHz Ivy Bridge (第三代Core i系列处理器)i7-3632QM的环境上。

     

          测试吞吐量的时候,是通过每一种实现都重复测试超过5次,每一次都运行5秒以上,以保证系统足够预热,下面的结果都是第5次之后平均每秒吞吐量。为了更像一个典型的java应用;没有采用会导致明显减少差异的线程依附性(thread affinity)和多核隔离(core isolation )技术;

    结果:



     

     

     

     

          上述图表的原始数据可以在这里找到

    分析:

          结果里面真正令我吃惊的是ReentrantReadWriteLock的性能,我没有想到的是,在这样的场景下它在读和少量写之间取得的巨大的平衡性,

     

          我主要的收获:

          1、StampedLock 对现存的锁实现有巨大的改进,特别是在读线程越来越多的场景下:

          2、StampedLock有一个复杂的API,对于加锁操作,很容易误用其他方法;

          3、当只有2个竞争者的时候,Synchronised是一个很好的通用的锁实现;

          4、当线程增长能够预估,ReentrantLock是一个很好的通用的锁实现;

          5、选择使用ReentrantReadWriteLock时,必须经过小心的适度的测试 ;所有重大的决定,必须在基于测试数据的基础上做决定;

          6、无锁的实现比基于锁的算法有更好短吞吐量;

     

    结论:

          非常开心能看到无锁技术对基于锁的算法的影响; 乐观锁的策略,实际上就是一个无锁算法技术。

          以我的经验看,教学和开发中的无锁算法,不仅能显著改善吞吐量;同时他们也提供更低的延迟。

    展开全文
  • 尹成JAVA高并发算法

    2020-12-12 11:21:42
    掌握数据结构和算法,可称为算法工程师!这是成为架构师的基础,有Google算法大神亲授。我保证你可以写出时空复杂度都很优的架构。有人专门答疑哟!你想要成为架构工程师吗?立即点击报名按钮吧! 北上广容不下肉身...
  • 单个MapReduce作业中基于Hadoop并发算法:MRPack是MapReduce实现的一种变体,其中多个相关算法可以在单个MapReduce作业中同时执行。 在MRPack中,所有算法都在Map and Reduce编程模型中实现,然后所有这些算法都在...
  • 包括并发的基础理论知识、不同并发模型的选择与适用环境、编写并发程序的基本步骤,并发算法的正确性证明与性能评价,以及在编写并发程序时遵循的一些指导原则等
  • 什么是并发?和并行的区别? 单个处理器上采用单核处理多个任务即为并发,在这种情况下,操作系统的调度程序会频繁且迅速地从一个任务切换到另一个任务,因此看起来所有任务是同时进行的; 而并行是在不同的计算机...

    一. 什么是并发?和并行的区别?

    单个处理器上采用单核处理多个任务即为并发,在这种情况下,操作系统的调度程序会频繁且迅速地从一个任务切换到另一个任务,因此看起来所有任务是同时进行的;
    而并行是在不同的计算机、处理器或处理器核心上同时运行多个任务

    二. 为什么需要设计并发程序?

    简单来说就是为了提高系统性能,提高系统资源(cpu)的利用率,将CPU的计算能力发挥到极致。

    但是并发应用程序会出现很多问题,如下:

    1. 数据竞争:两个或多个任务同时对一个共享变量进行写入操作,那么该变量的最终结果取决于这些任务的执行顺序。
    2. 死锁: 例如当任务A需要等待任务B释放某个资源才能往下执行,而任务B又需要等待任务A释放某个资源才能往下执行,这样就形成了死锁。
      死锁形成的四个必要条件:
      (1)互斥条件:死锁中涉及的资源不是 同时共享的,任意时刻只能被一个任务占有;
      (2)不可抢占条件:对于某个任务已占有的资源不能被其他任务抢占;也就是说,该资源只能由占有它的任务自己释放;
      (3)占有并等待条件:当某个任务在请求获取其他资源时,不会释放掉已经占有的资源;
      (4)循环等待:例如任务1等待任务2占有的资源,任务2等待任务3占有的资源,而任务3等待任务1占有的资源。这样就形成了循环等待。
      处理死锁的方法:
      (1)忽略:即出现死锁则停止应用程序并且重新执行,由于简单,是常用的机制;
      (2)检测:检测到死锁,则结束某个任务并强制释放某一资源;
      (3)预防:预防发生死锁的四个必要条件中的一条或多条;
      (4)规避:在某一任务执行之前得到该任务需要的所有资源信息,这样就能判断该任务是否可以执行。
    3. 资源不足:某个任务无法获取维持其继续运行的资源,或者等待时间过长,这就需要考虑任务占有资源的时间因素,来实现一个算法确保公平性原则。
    4. 活锁:可能是同步机制设置的不好,例如:有两个任务,都需要用到资源1和资源2,假设任务1获得了资源1并对资源1加了锁,任务2获得了资源2并对资源2加了锁。当它们获取不到所需的资源时,就会释放已有的资源并且重新开始循环(破坏了死锁发生的四个条件之一)。这种情况可以无限地持续下去,所以这两个任务都不会结束自己的执行过程。
    5. 优先权反转:当一个低优先权的任务获得了高优先权需要的资源时,低优先权的任务则会在高优先权任务之前执行。

    三. 处理并发程序中的问题:同步

    同步是一种协调多个任务以获得预期结果的机制,主要有两种方式:

    1. 控制同步:当一个任务依赖于另一个任务结束时,第二个任务不能在第一个任务之前完成;
    2. 数据访问同步:两个或多个任务访问不能同时访问共享变量。即在任意时间里,只有一个任务可以访问该变量。
      同步算法会为并发程序带来额外的开销,这就涉及并发算法的粒度,如果算法有着粗粒度,则同步机制的开销就小,反之则大。

    ps:任务的通信方式有两种:1.共享内存:通常用于在同一计算机上执行多任务的情况,当涉及到写入的程序段需要使用同步机制将其设置为临界段 2. 消息传递:通常用于在不同计算机上执行多任务的情况,如果发送方保持阻塞并等待响应,那么就是同步通信;如果发送方在发送消息后继续执行自己的流程,那么就是异步通信

    四. 设计并发算法的方法论

    该方法论基于Intel公司在其“Threading Methodologgy:Principles and Practices"文档中给出的方法论。
    起点:算法的一个串行版本(很重要),体现在以下两方面:
    (1)算法的串行版本可以用来测试并发算法是否产生了正确的结果(测试阶段)
    (2)算法的串行版本可以用来与并发算法比较吞吐量,以此来观察并发处理是否能够改善响应时间提升算法一次性所能处理的数据量(调整阶段)

    方法论有以下5个步骤:
    (1)分析: 通过算法的串行版本来寻找代码中哪些部分可以以并行方式运行。通常关注的是那些执行过程花费时间较多或者执行代码较多的部分,实现这些部分的并发版本则能获得较大的性能改进。
    在这个过程中使用循环排查的方法,让其中某些部分的代码独立于其他部分的代码

    (2)设计:根据同步机制实现的两种方式可以有两种设计方式:
    A. 任务分解:将代码划分成两个或多个可以立刻执行独立任务时,即任务分解。当其中某些任务可能必须按照某种给定的顺序来执行时,则必须使用控制同步的机制来实现。
    B. 数据分解:当使用同一任务的多个实力分到对数据集的一个子集进行处理时,即数据分解。当这些任务需要修改数据时,则必须使用数据同步的机制。
    关于对任务的分解,需要注意的是分解后的算法粒度大小,如果分割成很多小任务(粒度过小),则实现同步机制所需额外引入的代码就会导致性能下降。如果粒度较大,分割的任务数量少于核数,那么就没有充分利用全部的资源。

    (3)实现:用java的线程库

    (4)测试:根据算法的串行版本来验证并发版本算法得到的结果是否正确

    (5)调整:对比并发算法和串行算法的吞吐量,如果性能没有提升,则重新审查该算法找出原因修改。

    展开全文
  • 一、串行JDK1.5前的默认算法缺点是只有一个线程,执行垃圾回收时程序停止的时间比较长语法-XX:+UseSerialGC新生代、老年代使用串行回收新生代复制算法老年代标记-压缩示例图测试代码 //-Xmx20m -Xms20m -Xmn2m -XX:...
    一、串行
    1. JDK1.5前的默认算法
    2. 缺点是只有一个线程,执行垃圾回收时程序停止的时间比较长
    3. 语法
      1. -XX:+UseSerialGC
      2. 新生代、老年代使用串行回收
      3. 新生代复制算法
      4. 老年代标记-压缩
    4. 示例图
    5. 测试代码
     //-Xmx20m -Xms20m -Xmn2m -XX:+UseSerialGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
            byte[] b = null;
            for (int i = 0; i < 7; i++)
            {
                b = new byte[3 * 1024 * 1024];
            }
    串行的关键字是DefNew(年轻代)、Tenured(年老代)、Perm(永久代)
    0.162: [GC0.162: [DefNew: 1562K->191K(1856K), 0.0030044 secs]
    0.165: [Tenured: 15917K->3820K(18432K), 0.0059132 secs] 16922K->3820K(20288K), 
    [Perm : 2890K->2890K(21248K)], 0.0090042 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 


    二、并行
    1. 多个线程执行垃圾回收
    2. 适合于吞吐量的系统,回收时系统会停止运行
    3. 语法
      1. -XX:+UseParNewGC(新生代使用并行收集器,老年代使用串行回收收集器)
        关键字(ParNew)
      2. -XX:+UseParallelGC(新生代使用并行回收收集器,老年代使用串行收集器)
      3. -XX:+UseParallelOldGC(新生代,老年代都使用并行回收收集器
        关键字(PSYoungGen)
      4. -XX:+UseConcMarkSweepGC(新生代使用并行收集器,老年代使用CMS)
      5. -XX:ParallelGCThreads 限制并行线程数量
      6. -XX:MaxGCPauseMills  GC最大停顿毫秒数
      7. -XX:GCTimeRatio 垃圾回收占用的CPU时间比例,默认99代表最大运行1%时间做GC
      8. 新生代复制算法
      9. 老年代标记-压缩
    4. 示例图
    5. UseParNewGC 代码同串行,年轻代并行,年老代串行 
      -Xmx20m -Xms20m -Xmn2m -XX:+UseParNewGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
           
      0.193: [GC0.193: [ParNew: 1601K->192K(1856K), 0.0093101 secs]0.202: [Tenured: 15948K->3834K(18432K), 0.0060758 secs] 16961K->3834K(20288K), [Perm : 3144K->3144K(21248K)], 0.0154452 secs] [Times: user=0.01 sys=0.00, real=0.02 secs] 
    6. UseParallelGC 功能同UseParNewGC 
    7. UseParallelOldGC 代码同串行,年轻代、年老代都并行 
    0.141: [GC [PSYoungGen: 1024K->488K(1536K)] 1024K->624K(19968K), 0.0166419 secs] [Times: user=0.03 sys=0.00, real=0.02 secs] 
    0.212: [GC [PSYoungGen: 1012K->504K(1536K)] 16509K->16157K(19968K), 0.0019856 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    0.215: [GC [PSYoungGen: 504K->504K(1536K)] 16157K->16181K(19968K), 0.0029741 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    0.218: [Full GC [PSYoungGen: 504K->0K(1536K)] [ParOldGen: 15677K->3810K(18432K)] 16181K->3810K(19968K) [PSPermGen: 2891K->2890K(21504K)], 0.0133807 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 

    三、并发
    1. 系统和垃圾回收一起执行,系统不会暂停
    2. 适合于响应要求高的系统,回收时系统不会停止运行
    3. 语法
      1. -XX:+UseConcMarkSweepGC设置年老代为并发收集,年轻代并行,适合于响应要求高的系统
    0.206: [GC0.206: [ParNew: 1603K->192K(1856K), 0.0038214 secs]0.210: [CMS: 15945K->3836K(18432K), 0.0084133 secs] 16963K->3836K(20288K), [CMS Perm : 3120K->3119K(21248K)], 0.0123102 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 

    Pid is:8008
    标记-清除算法
    2.217: [GC [1 CMS-initial-mark: 9980K(18432K)] 10450K(20288K), 0.0005452 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    2.225: [CMS-concurrent-mark-start]
    2.239: [CMS-concurrent-mark: 0.014/0.014 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
    2.239: [CMS-concurrent-preclean-start]
    2.240: [CMS-concurrent-preclean: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    2.240: [GC[YG occupancy: 469 K (1856 K)]2.240: [Rescan (parallel) , 0.0002922 secs]2.241: [weak refs processing, 0.0000111 secs]2.241: [scrub string table, 0.0001527 secs] [1 CMS-remark: 9980K(18432K)] 10450K(20288K), 0.0005009 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    2.241: [CMS-concurrent-sweep-start]
    2.241: [CMS-concurrent-sweep: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    2.241: [CMS-concurrent-reset-start]
    2.241: [CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    展开全文
  • 以往的算法比如标记整理,复制等都是假定回收时处于STW状态,会暂停其他的线程,而并发算法允许和其他线程同时运行。 三色模型 将对象分为三色 黑:对象连同引用都被扫描过 白:对象未被扫描过 灰:对象被扫描过,...
  • 在并发上下文中,非阻塞算法是一种允许线程在阻塞其他线程的情况下访问共享状态的算法。...阻塞并发算法 一个阻塞并发算法一般分下面两步: 执行线程请求的操作 阻塞线程直到可以安全地执行操作 很...
  • 基于动态决策的并发控制算法
  • Java并发系列-27、非阻塞算法

    千次阅读 2016-12-06 12:00:47
    在并发上下文中,非阻塞算法是一种允许线程在阻塞其他线程的情况下访问共享状态的算法。在绝大多数项目中,在...阻塞并发算法 一个阻塞并发算法一般分下面两步: 执行线程请求的操作阻塞线程直到可以安全地执行操作
  • 今天我们就记录介绍一下高并发情况下,最常用的两种限流算法:漏桶算法和令牌桶算法的原理,方便更好的理解。比如nginx中的限制访问速率的算法就是漏桶算法。 原文详情请查看我的个人博客: 右键在新标签页中...
  • 研究了一种基于多粒度锁的并发控制算法,包括其多粒度锁锁、锁表数据结构及锁操作的算法步骤。算法可以降低冲突发生的概率和事务的夭折数,减少事务重启,有利于满足事务截止期的要求,提高事务的并发度。在验证算法...
  • 并发中所谓的非阻塞算法是允许线程访问共享状态(或以其他方式进行协作或通信)而不会阻塞所涉及...为了更好地理解阻塞和非阻塞并发算法之间的区别,我将首先说明阻塞算法,接着再说明非阻塞算法。 阻塞并发算法 ...
  • 在并发上下文中,非阻塞算法是一种允许线程在阻塞其他线程的情况下访问共享状态的算法。在绝大多数项目中,在算法中如果一个线程的挂起没有导致其它的线程挂起,我们就说这个算法是非阻塞的。...阻塞并发算法 一...
  • 协同绘图是计算机支持的协同工作(CSCW)的重要研究...本文在基于复制结构的并发控制策略分析的基础上,提出了并发访问控制策略模型,并给出了一个有效的适合绘图对象并发控制算法,在实际应用中表现出较好的协作性能。
  • public class Foo { // 利用 volatile 的可见性,设置并修改屏障 volatile int stage = 1; public void first(Runnable printFirst) throws InterruptedException { printFirst.run();...
  • 并发限流算法

    2021-03-10 16:47:02
    在高并发系统中,有很多手段来保护系统,如缓存、降级和限流等。 缓存:让数据尽早进入缓存,离程序近一点,不要大量频繁的访问DB,可提供系统访问速度和增大系统处理能力。 降级:当服务出问题或者影响到核心流程...
  • 近年来,在并发算法领域的大多数研究都侧重于非阻塞算法,这种算法用底层的原子机器指令(例如比较并发交换指令)代替锁来确保数据在并发访问中的一致性。非阻塞算法被广泛的用于在操作系统和JVM中实现线程/进程调度...
  • 基于日志查询并发调度算法优化 背景: 高峰日志查询时,单机开多并发查询日志,会出现io负载过重,影响服务稳定性,优化单机并发处理。 名词解释:A、B、C 机器列表 A1 为机器A的第一个实例 前提:脚本获取机器...
  • 并发编程 CAS算法

    2018-12-17 22:44:43
    对于并发控制而言,我们平时用的锁(synchronized,Lock)是一种悲观的策略。它总是假设每一次临界区操作会产生冲突,因此,必须对每次操作都小心翼翼。如果多个线程同时访问临界区资源,就宁可牺牲性能让线程进行...
  • 难点:在标记对象过程中,对象引用关系正在发生改变 三色标记: G1为什么使用SATB
  • 并发连接数算法

    2012-06-07 13:18:36
    并发连接数 = PV / 统计时间 * 页面衍生连接次数 * http响应时间 * 因数 / web服务器数量 PV = 并发连接数 * 统计时间 * web服务器数量/ 页面衍生连接次数 / http响应时间 / 因数 解释: 统计时间 : pv统计...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,233
精华内容 4,893
关键字:

并发算法