美文网首页
23 cas 自旋锁

23 cas 自旋锁

作者: 滔滔逐浪 | 来源:发表于2020-07-18 21:11 被阅读0次

1, 传统synchronized 锁缺陷:
悲观: 如果没有获取到锁的情况下,会让当前的线程变为阻塞的状态,释放CPU
执行权,效率非常低。
同步中嵌套同步,可能会出现死锁。
乐观锁: 本质上没有锁,,没有死锁现象,而且效率也比较高,不会释放cpu
执行权,通过预期比较或者版本号控制。
cas无锁
CAS: Compare and Swap,翻译成比较并交换。 执行函数CAS(V,E,N)
CAS有3个操作数,内存值V,旧的预期值E,要修改的新值N。当且仅当预期值E和内存值V相同时,将内存值V修改为N,否则什么都不做。


image.png
image.png

1.Cas 是通过硬件指令,保证原子性
2.Java是通过unsafe jni技术
3.原子类: AtomicBoolean,AtomicInteger,AtomicLong 等使用 CAS 实现。
使用AtomicInteger实现自增

package com.taotao.metithread;

import java.util.concurrent.atomic.AtomicLong;

/**
 *@author tom
 *Date  2020/7/18 0018 21:22
 *
 */
public class Test002  extends  Thread{
    private  static AtomicLong atomicLong=new AtomicLong();

    @Override
    public void run() {
        while (atomicLong.get()<10000){

        long l=atomicLong.incrementAndGet();
        System.out.println(Thread.currentThread().getName()+","+l);
    }

    }

    public static void main(String[] args) throws InterruptedException {
        Long starttime=System.currentTimeMillis();
        Test002 t1=new Test002();
        Test002 t2=new Test002();
        t1.start();
      //  t2.start();
        t1.join();
      //  t2.join();
        Long end=System.currentTimeMillis();
        System.out.println(end-starttime);
    }
}




public final long getAndAddLong(Object var1, long var2, long var4) {
    long var6;
    do {
        var6 = this.getLongVolatile(var1, var2);
    } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));

    return var6;
}

Var6 就是为旧的预期值:0 E
Var1,var2 就是我们共享变量值:V
Var6+Var4 就是我们的新值N

如果Var6(E)==Var1,var2 (V) 则修改V为N;

AtimicLong 实现乐观锁:

111

package com.taotao.metithread;

import java.io.InputStream;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.IntStream;

/**
 *@author tom
 *Date  2020/7/18 0018 21:55
 *基于cas 实现乐观锁
 */
public class AtomicTrylock {
    private AtomicLong atomicLong = new AtomicLong(0);
//设计锁 java  aqs 持有同一把锁,持有人state 为0 没有线程持有锁,获取到锁state为1;

    private Thread lockcutrrentThread;

    /***
     * 获取锁 将内存值改为1
     * @return
     */
    public boolean mayiktTryLock() {
        //v=0 e=0 v==e v=1
        //预期值,更新值
        boolean result = atomicLong.compareAndSet(0, 1);
        if (result) {
            lockcutrrentThread = Thread.currentThread();
        }
        return result;
    }

    /**
     * 释放锁 ji8ang内存值改为0
     * @return
     */
    public boolean mayiktUnlock() {

        if(lockcutrrentThread !=null && lockcutrrentThread !=Thread.currentThread()){
            return  false;
        }
        boolean result = atomicLong.compareAndSet(1, 0);
        return result;

    }

    public static void main(String[] args) {
        AtomicTrylock atomicTrylock =new AtomicTrylock();
        IntStream.range(1,10).forEach((i)-> new Thread(()->{
            try {
                boolean result=atomicTrylock.mayiktTryLock();
                if(result){
                    System.out.println(Thread.currentThread().getName()+",获取锁成功");
                }else {
                    System.out.println(Thread.currentThread().getName()+",或区域锁失败——");
                }
            }catch (Exception e){
                e.printStackTrace();
                atomicTrylock.mayiktUnlock();
            }finally {
                atomicTrylock.mayiktUnlock();
            }
        }).start());

    }
}



Cas Aba的问题

Cas主要检查 内存值V与旧的预值值=E是否一致,如果一致的情况下,则修改。
这时候会存在ABA的问题:
如果将原来的值A,改为了B,B有改为了A 发现没有发生变化,实际上已经发生了变化,所以存在Aba问题。
解决办法:通过版本号码,对每个变量更新的版本号码做+1

解决aba问题是否大:概念产生冲突,但是不影响结果,换一种方式 通过版本号码方式。

image.png

AtomicMarkableReference
(1)第一个参数expectedReference:表示预期值。
(2)第二个参数newReference:表示要更新的值。
(3)第三个参数expectedStamp:表示预期的时间戳。
(4)第四个参数newStamp:表示要更新的时间戳。

package com.taotao.metithread;

import java.util.concurrent.atomic.AtomicStampedReference;

/**
 *@author tom
 *Date  2020/7/18 0018 22:43
 *
 */
public class Test004 {
    // 注意:如果引用类型是Long、Integer、Short、Byte、Character一定一定要注意值的缓存区间!
    // 比如Long、Integer、Short、Byte缓存区间是在-128~127,会直接存在常量池中,而不在这个区间内对象的值则会每次都new一个对象,那么即使两个对象的值相同,CAS方法都会返回false
    // 先声明初始值,修改后的值和临时的值是为了保证使用CAS方法不会因为对象不一样而返回false
    private static final Integer INIT_NUM = 1000;
    private static final Integer UPDATE_NUM = 100;
    private static final Integer TEM_NUM = 200;
    private static AtomicStampedReference atomicStampedReference = new AtomicStampedReference(INIT_NUM, 1);

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Integer value = (Integer) atomicStampedReference.getReference();
                int stamp = atomicStampedReference.getStamp();
                System.out.println(Thread.currentThread().getName() + " : 当前值为:" + value + " 版本号为:" + stamp);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // value 旧值 内存中的值   UPDATE_NUM 修改的值
                if (atomicStampedReference.compareAndSet(value, UPDATE_NUM, 1, stamp + 1)) {
                    System.out.println(Thread.currentThread().getName() + " : 当前值为:" + atomicStampedReference.getReference() + " 版本号为:" + atomicStampedReference.getStamp());
                } else {
                    System.out.println("版本号不同,更新失败!");
                }
            }
        }, "线程A").start();

    }
}


线程A : 当前值为:1000 版本号为:1
线程A : 当前值为:100 版本号为:2

Process finished with exit code 0

相关文章

  • Java多线程-深入

    CAS Compare And Swap (Compare And Exchange) / 自旋 / 自旋锁 / ...

  • 23 cas 自旋锁

    1, 传统synchronized 锁缺陷:悲观: 如果没有获取到锁的情况下,会让当前的线程变为阻塞的状态,释放C...

  • 多线程(6) — CAS自旋及问题

    自旋锁CAS: CAS:Compare and Swap, 即比较交换。在轻量级锁升级为重量级锁时就用到了自旋锁C...

  • 锁的总结

    序号锁名称应用实例1乐观锁CAS2悲观锁synchronized、vector、hashtable3自旋锁CAS4...

  • 极简CAS

    CAS 乐观锁 compare and then swap else 自旋 Atomic的核心操作就是CAS(co...

  • Java CAS

    CAS和LockSupport可以说贯穿了java并发包(自旋锁 + CAS + LockSupport + 内存...

  • Java自旋锁的分类

    自旋锁 自旋锁(spin lock)是一个典型的对临界资源的互斥手段,自旋锁是基于CAS原语的,所以它是轻量级的同...

  • CAS(自旋锁)

    synchronized能够保证线程安全,但synchronized是重量级锁,性能低;可以使用CAS进行锁优化,...

  • 自旋锁和互斥锁的区别 java中lock Syntronized

    自旋锁和互斥锁的区别 java中lock Syntronized区别无锁编程以及CAS

  • 多线程与高并发知识点简述

    CAS和Atomic包 CAS操作流程: JDK5之后发布了基于乐观锁思想的自旋锁(无锁)java.util.co...

网友评论

      本文标题:23 cas 自旋锁

      本文链接:https://www.haomeiwen.com/subject/kigfkktx.html