无锁操作简介、集锦

无锁操作集锦:
1.适用场景:
  多个线程同时抢占同一个资源,并对其进行写(修改)操作

2.几个基本的概念:
  寄存器:是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和位址。在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中,包含的寄存器有累加器(ACC)。
  线程栈:每个线程都有自己独占的线程栈,栈里存放着此线程的全局变量和局部变量、方法。
  volatile关键字:被其修辞的变量不会进行计算机指令重排,并且此变量的值存储在寄存器中。
  CAS:即compare-and-set,计算机最底层的原子操作。

3.常用场景:
  1).修改配置"热生效",通过一个变量控制另一个线程中的循环:
    方法:声明一个volatile的boolean变量,一个线程监控配置是否修改或者指定的规则是否满足,来修改此volatile变量的值;因其值保存在寄存器中,所以在此变量值变后,另一个线程进行条件判断时就会捕获到变化,并对其做出相应的反应。

  2).无锁队列:
    方法:push/pop操作的逻辑如下:声明一个AtomicBoolean的变量control,默认值为false
      while(true){
        if(control.compareAndSet(false,true)){
          process logic;
          control.set(false);
          break;
        }

      }
    通过最底层的原子操作来实现无锁队列,但是没有获得锁的线程会一直while循环判断if条件,cpu 100%或者更高

  3).无锁循环队列的思想解决数据的缓存
    方法:大数据量、高并发的网络编程中,开辟一个大内存做数据缓存对提高程序的性能显得尤为重要,这里将详细介绍去除锁的技巧:
做数据缓存的目标:数据的安全性(接收的数据没有被copy前,不能被覆盖)、数据的接收处理要高效使模块达到数据处理要求(千兆网500bps,相当于普通SATA盘的IO能力)
    处理中会遇到的所有情况:
      a).第一次接收数据,可以从0存放到缓存数组的cacheBytes.length;
      b).当接收的数据存放到cacheBytes.length时,要进行转头操作;转头后,数据接收只能存放到处理端指针最后一次处理的位置
      c).当接收端指针和处理端指针位置重合时有两种情况:一是处理端处理太慢,接收端存放赶上处理端;二是处理端处理完所有的数据,和接收端指针重合
    无锁的方案要能安全的处理以上3种情况,新添一个volatile变量processBeforeRead,默认值为true,当接收端转头后,将processBeforeRead修改为true;当处理端转头后将processBeforeRead修改为false;当接收端指针和处理端指针指向同一个位置时,根据processBeforeRead的值来决定是扔掉数据(false)还是存放数据到cacheBytes.length(true)。
    后在google上看到循环无锁队列的实现,和此方案思想相同。

4.总结:
  想要解决锁的问题,根绝实际情况列出可能的所有情况,然后巧妙的利用新变量去满足所有的情况即可;当这种情况较为常见时,就被抽象出来成为大家所熟知的xxx无锁操作,但是却忘记了解决问题的思路...

你可能感兴趣的:(简介)