zoukankan      html  css  js  c++  java
  • Java锁机制(二)

    CAS无锁机制

    CAS:Compare and Swap,即比较再交换。

    Java内存模型:JMM(Java Memory Model)
    在内存模型当中定义了一个主内存,所有声明的实例变量都存在于主内存当中,主内存的数据会共享给所有线程,每一个线程有一块工作内存,工作内存当中主内存数据的副本
    当更新数据时,会将工作内存中的数据同步到主内存当中

    CAS无锁机制:本身无锁,采用乐观锁的思想,在数据操作时对比数据是否一致,如果一致代表之前没有线程操作该数据,那么就会更新数据,如果不一致代表有县城更新则重试
    CAS当中包含三个参数CAS(V,E,N),V标识要更新的变量,E标识预期值,N标识新值

    运行过程:
    1.线程访问时,先会将主内存中的数据同步到线程的工作内存当中
    2.假设线程A和线程B都有对数据进行更改,那么假如线程A先获取到执行权限
    3.线程A先会对比工作内存当中的数据和主内存当中的数据是否一致,如果一致(V==E)则进行更新,不一致则刷新数据,重新循环判断
    4.这时更新完毕后,线程B也要进行数据更新,主内存数据和工作内存数据做对比,如果一致则进行更新,不一致则将主内存数据重新更新到工作内存,然后循环再次对比两个内存中的数据
    直到一致为止


    CAS无锁机制存在一个问题
    ABA问题,如果将原来A的值改为了B,然后又改回了A,虽然最终结果没有发生改变,但是在过程中是对该数据进行了修改操作
    解决该问题:在Java中并发包下有一个原子类:AtomicStampedReference,在该类当中通过版本控制判断值到底是否被修改
    解释:如果对值进行了更改则版本号+1,那么在CAS当中不仅仅对比变量的值,还要对比版本号,如果值和版本号都相等则代表没有被修改,如果有一方不相等代表进行过更改
    那么就从主内存中重新刷新数据到工作内存然后循环对比,直到成功为止

    保证线程安全的三个方面:
    1.原子性:保证同一时刻该资源只能有一个线程访问修改,其他线程阻塞等待,例如Atomic包,锁
    2.可见性:一个线程对于主内存的数据操作对于其他线程是可见的
    3.有序性:一个线程观察其他线程中指令执行顺序,由于指令重排序存在,观察结果一般杂乱无序
    原子性: 互斥访问,Atomic包,CAS算法,Synchronized,Lock

    可见性:synchronized,volatile

    顺序性:happends-before

    AQS抽象队列同步器

    AQS:全成AbstractQueueSynchronizer,抽象队列同步器,这个类在java.util.concurrent.locks包下
    它是一个底层同步工具类,比如CountDownLatch,Sammphore,ReentrantLock,ReentrantReadWriteLock等等都是基于AQS
    底层三个内容:
    1.state(用于计数器)
    2.线程标记(哪一个线程加的锁)
    3.阻塞队列(用于存放阻塞线程)

    在AQS当中,假设当前线程A要获取锁,如果获取到锁资源则将state改为1,然后记录当前线程,在线程A没有释放掉锁的情况下,那么其他线程访问时,
    会产生阻塞,那么会将阻塞线程放入到队列(双向链表)当中,当线程A使用完该锁,调用了unLock时,那么在队列当中等待的线程就有执行得机会,如
    果成功获取到锁则出队,如果没有获取到锁则让下一个等待线程去获取

  • 相关阅读:
    JAVA基础——编程练习(二)
    JAVA基础——面向对象三大特性:封装、继承、多态
    JVM内存
    50. Pow(x, n) (JAVA)
    47. Permutations II (JAVA)
    46. Permutations (JAVA)
    45. Jump Game II (JAVA)
    43. Multiply Strings (JAVA)
    42. Trapping Rain Water (JAVA)
    41. First Missing Positive (JAVA)
  • 原文地址:https://www.cnblogs.com/wishsaber/p/12576501.html
Copyright © 2011-2022 走看看