美文网首页工作生活
J.U.C之Atomic:Atomic相关概念

J.U.C之Atomic:Atomic相关概念

作者: 贪睡的企鹅 | 来源:发表于2019-07-03 23:05 被阅读0次

    Atomic相关概念

    线程安全问题

    从操作系统角度

    在操作系统中一个进程中所有线程共享进程的资源。其中重要的资源就是内存。

    我们可以把一个进程看成一个项目组,项目运行需要的会议室看做内存,在项目工作每一个员工看作是一线程。因此项目组被分配的会议室是可以被所有员工所共享的。同时员工的执行工作是需要CPU去调度的。如果多个成员被调度(线程)执行对会议室中墙面上同一个变量做+1操作时,很可能回发生线程安全问题。

    因为当他们执行如上操作本质上需要完成三个动作,首先员工需要将墙面上变量写入自己工作本中,当然这个本本可不是自己的是CPU分配的。然后对本上变量做+1操作,最后重写回墙面。如果A,B员工同时从墙面获取变量为1,并同时写回本子上做+1,那么最终墙面上结果为2,并不是期望的3,而这就是线程安全问题。这里cpu分配的本子就是CPU的高速缓存,也叫做CPU寄存器

    JMM角度

    我们将程序的内存划分为主内存和线程内存,主内存表示操作系统分配给进程的内存,而线程内存为CPU的高速缓存。

    悲观锁,乐观锁

    为了解决线程安全的问题,最有效的办法就加锁。而锁本身又可以分为两种,悲观锁乐观锁

    悲观锁

    java里面的synchronized就是悲观锁,它是一种独占锁。当多个线程访问用synchronized块中的资源时需要竞争获取锁,获取锁的线程可以进入synchronized块执行,其他线程进入等待队列等待并阻塞线程。当获取线程的锁完成释放锁,会通知回复等待队列中线程从阻塞中被唤醒,并重新竞争锁。

    乐观锁

    他的核心思路就是,当多个线程同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败。乐观锁并不需要加锁。只需要每个线程知道其他线程是否和自己一样对同一个变量在进行操作(存在竞争关系)。

    乐观锁的原理是在更新某个变量时会先获取变量的原始值,在操作更新时比对当前变量的值和原始值是否相同,如果不相同则说明存在其他线程正在操作同一数据(存在竞争关系),则失败返回。如果相同则执行修改。

    乐观锁 VS 悲观锁

    如果同步块中的资源执行很快,而线程任务很多悲观锁会导致线程频繁的挂起,唤醒消耗了大量的系统资源。

    悲观锁加锁,解锁会加慢程序的响应时间。

    对于乐观锁而已最麻烦便是ABA问题,如果一个线程竞争变成从A改为B有再次改成A,这对另一个线程来说会无法察觉。而ABA最好的解决办法就是时间戳或者版本计数,每次更新都对版本+1

    CAS

    CAS是Unsafe类compareAndSwap方法的简称,compareAndSwap方法提供了JAVA乐观锁技术实现。其组要实现类为Unsafe

    compareAndSwap API

    compareAndSwap 尝试将变量的值更新为 x。如果更新成功,返回 true;否则,返回 false

    //更新变量值为x,如果当前值为expected,o:对象 offset:偏移量 expected:期望值 x:新值
    
    public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object x);
      
    public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
      
    public final native boolean compareAndSwapLong(Object o, long offset, long expected, long x);
    

    相关文章

      网友评论

        本文标题:J.U.C之Atomic:Atomic相关概念

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