Java 并发锁 CAS基本使用和源码分析

1:介绍

CAS也是并发编程常用的类之一,它是基于原子性的操作来进行锁机制的。

实现原子操作是可以使用锁来执行的,当我们使用synchronized关键字的时候,是基于阻塞机制的锁,当一个线程拥有了锁,其他线程在调用的时候就必须等待。

当线程出现高并发,资源竞争激烈,还有可能死锁等情况,使用synchronized这种粗粒度的锁就有点不太好使用了。这个时候就需要原子操作了(本人喜欢叫乐观锁)。

当前的电脑处理器都支持CAS()指令,每一个CAS操作过程都包含三个运算符:一个内存地址,一个期望的值,一个新值。当期望的值和内存地址存放的值一样的时候,

就将新值赋值到内存地址上面的值,如果不一样就不做任何的事情,返回内存地址的里面的值。

 

CAS实现锁的机制:在一个循环里面一直在循环,直到新值赋值成功。一下就是简单的流程图:

 

 

 2:简单的代码实现

public class AtomicTest {
    static Integer count =100;
    static AtomicInteger atomicInteger = new AtomicInteger(0);
    static CountDownLatch latch = new CountDownLatch(count);

    private static class Worker implements Runnable{
        @Override
        public void run() {
            atomicInteger.getAndIncrement();
            latch.countDown();
        }
    }

    public static void main(String[] args) throws Exception {
        for (int i=0;i<count;i++){
            Thread thread = new Thread(new Worker());
            thread.start();
        }
        latch.await();
        System.out.println("计算之后的结果:"+atomicInteger.get());
    }
}

结果

以上就是实现了一个简单的累加计数器。

3:源码解析

当new AtomicInteger(0),就是将0复制到value上面。value是一个volatile修饰的,也就是当线程的对数据修改的时候,其他线程也会收到修改完之后的数据。

会初始化一个unsafe对象,还有一个静态代码,它里面就是做给内存地址赋值初始值的,返回valueOffset偏移量(方便在内存查找吧)。

由于objectFieldOffset是一个native方法,没法看到具体的代码(这里面只是个人的理解)。

 

 

 

 

 

 

 

当调用getAndIncrement方法的时候,又会继续调用unsafe.getAndAddInt方法,this当前对象,valueOffset是一个偏移量,1是我们要进行新增的值。

getAndAddInt方法,该方法是一个dowhile语句,也就是如果不满足条件就会一直循环。getIntVolatile方法就是将对象和偏移量来查找放在内存当中罪行的值,

然后将最新的值进行+1操作,compareAndSwapInt方法就是执行前面所说的替换操作,如果替换成功返回TRUE,替换失败返回FALSE。

返回拿到的内存地址存放的数据,不是新增之后的数据。

 

 

 

 

 

 

 

 

由于好多方法都是native修饰了,导致了源码不能看,所以就按本人理解的意思就行讲解。

 

3:CAS带来的问题

ABA问题

因为在执行CAS的时候,是进行值的比较,如果这个值之前进行+5,然后又进行-5,最终变成0,然后进行比较的还是0所以就行了替换了。

很显然这个值是变化的了。解决的办法就是加一个版本号,1A->2B->3C,这样子就可以防止值进行修改就不知道了。

 

性能问题

因为CAS是采用自旋的方式进行锁的操作,所以会对性能有一定的影响。

 

只能保证一个变量的共享

如果我们要有多个变量的话,怎么办?采用对象的方式进行替换,JDK提供了AtomicReference类来保证对象的原子性。

 

以上就是简单的CAS操作,纯属个人了理解,有不对的地方往告知,谢谢!!!

 

当然atomic包下面还有很多个类,我会尽可能都解析出来的。

 

posted @ 2020-02-28 23:54  陌然浅笑  阅读(267)  评论(0)    收藏  举报