21道并发编程口试题(9)

    ABA问题,假如将本来A的值改为了B,然后又改回了A,固然最终功效没有产生改变,可是在进程中是对该数据举办了修改操纵

    办理该问题:在Java中并发包下有一个原子类:AtomicStampedReference,在该类傍边通过版本节制判定值到底是否被修改

    表明:假如对值举办了变动则版本号+1,那么在CAS傍边不只仅比拟变量的值,还要比拟版本号,假如值和版本号都相等则代表没有被修改,假如有一方不相等代表举办过变动

    那么就从主内存中从头刷新数据到事情内存然后轮回比拟,直到乐成为止~

16.AQS

  AQS:全称AbstractQueueSynchronizer,抽象行列同步器,这个类在java.util.concurrent.locks包下

            它是一个底层同步东西类,好比CountDownLatch,Sammphore,ReentrantLock,ReentrantReadWriteLock等等都是基于AQS

    底层三个内容:

      1.state(用于计数器)

       2.线程标志(哪一个线程加的锁)

       3.阻塞行列(用于存放阻塞线程)

  AQS提供了一种实现阻塞锁和一系列依赖FIFO期待行列的同步器的框架,如下图所示。AQS为一系列同步器依赖于一个单独的原子变量(state)的同步器提供了一个很是有用的基本。子类们必需界说改变state变量的protected要领,这些要领界说了state是如何被获取或释放的。

    

21道并发编程面试题

   J.U.C是基于AQS实现的,AQS是一个同步器,设计模式是模板模式。

  焦点数据布局:双向链表 + state(锁状态)

  底层操纵:CAS

    

21道并发编程面试题

17.ReentrantLock底层实现

  ReentrantLock是基于AQS的,AQS是Java并发包中浩瀚同步组件的构建基本,它通过一个int范例的状态变量state和一个FIFO行列来完成共享资源的获取,线程的列队期待等。AQS是个底层框架,回收模板要领模式,它界说了通用的较为巨大的逻辑骨架,好比线程的列队,阻塞,叫醒等,将这些巨大但实质通用的部门抽取出来,这些都是需要构建同步组件的利用者无需体贴的,利用者仅需重写一些简朴的指定的要领即可(其实就是对付共享变量state的一些简朴的获取释放的操纵)。

  无参结构器(默认为非公正锁) 

public ReentrantLock() { sync = new NonfairSync();//默认长短公正的 }

    sync是ReentrantLock内部实现的一个同步组件,它是Reentrantlock的一个静态内部类,担任于AQS;

  带布尔值的结构器(是否公正)

public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync();//fair为true,公正锁;反之,非公正锁 }

    看到了吧,此处可以指定是否回收公正锁,FailSync和NonFailSync亦为Reentrantlock的静态内部类,都担任于synchronized;

18.ReentrantLock和synchronized之间的区别

synchronized 竞争锁时会一直期待;ReentrantLock 可以实验获取锁,并获得获取功效

synchronized 获取锁无法配置超时;ReentrantLock 可以配置获取锁的超时时间

synchronized 无法实现公正锁;ReentrantLock 可以满意公正锁,即先期待先获取到锁

synchronized 节制期待和叫醒需要团结加锁工具的 wait() 和 notify()、notifyAll();ReentrantLock 节制期待和叫醒需要团结 Condition 的 await() 和 signal()、signalAll() 要领

synchronized 是 JVM 层面实现的;ReentrantLock 是 JDK 代码层面实现

synchronized 在加锁代码块执行完可能呈现异常,自动释放锁;ReentrantLock 不会自动释放锁,需要在 finally{} 代码块显示释放

19.ReentrantReadWriteLock(读写锁)

  对比java中的锁(Lock in java)里Lock实现,读写锁更巨大一些;

  假设你的措施中涉及到对一些共享资源的读和写操纵,且写操纵没有读操纵那么频繁。在没有写操纵的时候,两个线程同时第一个资源没有任务问题,所以应该答允多个线程能在同时读取共享资源。可是假如有一个线程想去写这些共享资源,就不该该再有其他线程对该资源举办读或写(也就是说:读和读能共享,读和写不能共享,写和写不能共享)。这就需要一个读写锁来办理这个问题。在java5中java.util.concurrent包中已经包括读写锁;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsdjff.html