Interview [JAVA] lock base


1, the lock status

Lock state can only upgrade can not be downgraded.

  • No lock
    no lock to lock resources, all threads can access and modify the same resources, but at the same time only one thread can be modified successfully. Other modifications fail thread will continue to retry until the modification is successful, the principles and applications such as CAS is lock-free implementation.
  • Biased locking
    biased locking means for a synchronization code has been accessed by a thread, the thread that acquires the lock automatically, reducing the cost to acquire a lock.
  • Lightweight lock
    means that when the lock is biased locking time, be accessed by another thread, it will be upgraded to lightweight biased locking lock, another thread tries to acquire a lock in the form of spin, does not block, thereby enhancing performance. Cas solved by operating problems and spin lock spin more than a certain number of times or have a spin thread, a thread again to acquire the lock, the lock will be upgraded to lightweight heavyweight lock.
  • Heavyweight lock
    upgraded to heavyweight lock, wait for the lock thread will enter the blocked state.

2, optimistic and pessimistic locking lock

  1. Optimistic locking, each time to take the data that others will not be modified, updated and then determine when during this period there is no update data, you can use the version number of mechanisms for reading the multi-scene, to improve performance.
  2. Pessimistic locking, each time to take the data that others would amend, will be locked, you can use synchronized, an exclusive lock Lock, read-write locks and other mechanisms for writing more scenes to ensure the correct write operation.

    3, the spin lock spin lock and adaptability

  • Spin locks: refers to the time when a thread to acquire the lock if the lock has been acquired by another thread, the thread will wait for the cycle, and then continue to determine whether the lock can succeed, to acquire the lock until it exits the loop.
    Advantages: no thread context switch, reducing the time of the context switching.
    Problems: If the thread holding the lock of a long time, other threads into the circulation, consumption cpu.
  • 自适应自旋锁:指的是自旋的时间不固定,由前一个在同一个锁上自旋的时间和锁拥有者的状态来决定。如果在同一个对象上,刚刚通过自旋成功获取过锁,且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋很有可能再次成功。反之自旋操作很少成功获取锁,那么后面获取这个锁可能直接省略掉自旋的过程,直接阻塞线程。

4、公平锁与非公平锁

  1. 公平锁是指多个线程按照申请锁的顺序直接进入队列排队,队列中的第一个线程才能获取锁。
  2. 非公平锁是指线程先尝试获取锁,获取不到进入队列中排队,如果能获取到,则无需阻塞直接获取锁。

5、重入锁与非重入锁

重入锁:同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁,前提是锁对象是相同的。

6、共享锁与排他锁

  1. 共享锁是指一个锁可以被多个线程锁持有。
  2. 排它锁或者叫独享锁或者互斥锁 指锁一次只能被一个线程所持有。

7、读写锁

  1. 读锁是共享的,写锁是独占的。
  2. 读读之间不会互斥,读写互斥,写写互斥,读写锁提高了读的性能。

8、CAS

CompareAndSwap比较与交换,是一种无锁算法,原子类使用了CAS实现了乐观锁。
带来的问题:

  1. ABA问题
    解决思路在变量前面加版本号,每次变量更新的时候都将版本号 1,每次更新的时候要求版本>=当前版本(AtomicStampedReference)

  2. 循环时间长开销大,CAS操作如果长时间执行不成功,会导致其一直自旋,cpu消耗大。
  3. 只能保证一个共享变量的原子操作。
    可以把多个变量放在一个对象里面进行CAS操作。

9、锁优化

9.1、锁升级
  1. 偏向锁的升级
    线程A获取锁对象时,会在java对象头和栈帧中记录偏向的线程A的id,线程A再次获取锁时,只需要比较java头中的线程id与当前Id是否相等,如果一致则无需通过cas加锁解锁。如果不一致,说明有线程B来获取锁,那么要判断java头中偏向锁的线程是否存活,如果没有存活,锁对象被置为无锁状态,线程B可将锁对象置为B的偏向锁。如果存活,则查看A是否还需要继续持有对当前锁,如果不需要持有,则将锁置为无锁状态,偏向新的线程,如果还继续持有锁对象,则暂停A线程,撤销偏向锁,将锁升级为轻量级锁。
  2. 轻量级锁的升级
    线程A获取轻量级锁时会把锁的对象头复制到自己的线程栈针中,然后通过cas把对象头中的内容替换为A所记录的地址。此时线程B也想获取锁,发现A已经获取锁,那么线程B就自旋等待。等到自旋次数到了或者线程A正在执行,线程B自旋等待,此时来了线程C来竞争锁对象,这个时候轻量级锁就会膨胀为重量级锁。重量级锁会把未获得到锁对象的线程全部变为阻塞状态该,防止cpu空转。

    9.2、锁粗化

    将多个连续的加锁,解锁操作连接在一起,扩展成为一个范围更大的锁,避免频繁的加解锁操作。

    9.3、锁消除

    通过逃逸分析,去除不可能存在共享资源竞争的锁,通过这种方式消除没有必要的锁。

    10、synchronized底层实现

  • synchronized通过Monitor实现同步,Monitor依赖于底层操作系统互斥锁来实现线程同步。
  • java对象头是由markword(标记字段)和klass point(类型指针)组成。markword存储对象的hashcode,分代年龄和锁标志位信息。Klass point 指向对象元数据的指针,虚拟机通过这个指针来确定对象是哪个类的实例。
  • synchronized修饰同步代码块,是使用monitorenter和monitorexit来控制的,通过java对象头中的锁计数器。
  • 修饰方法时会将方法标识为ACCSYNCHRONIZE,JVM通过这个标志来判断方法是不是同步方法。

11、synchronized与ReentrantLock的区别

  1. 两者都是悲观锁,可重入锁。
  2. ReentrantLock 可中断,可以实现公平锁,可以绑定多个条件。
  3. ReentrantLock需要显示的调用锁和释放锁,synchronized属于java关键字,不需要显式的释放。

12、volatile关键字

  1. 保证变量内存可见。
  2. 禁止指令重排序。

volatile和synchronized的区别:

  • volatile不会阻塞,synchronized会阻塞。
  • volatile保证数据的内存可见性但不能保证原子性,synchronized两者都能保证。
  • volatile主要解决变量在线程之间的可见性,而synchronized主要解决多线程访问资源的同步性。

13、Atomic原子类实现

使用cas操作 volatile native方法保证同步。

14、AQS

AQS(AbstractQueuedSynchronizer)内部维护的是一个FIFO的双向同步队列,如果当前线程竞争锁失败,AQS会把当前线程以及等待状态信息构造成一个Node加入到同步队列中,同时在阻塞该线程。当获取锁的线程释放锁以后,会从队列中唤醒一个阻塞的节点线程。使用内部的一个state来控制是否获取锁,当state=0时表示无锁状态,state>0时表示已经有线程获取了锁。

15、AQS的组件

  1. semaphore 可指定多个线程同时访问某个共享资源。
  2. countDownLatch 一个线程A等待其他线程执行完成之后才继续执行。
  3. cyclicBarrier 一组线程等待至某个状态之后同时执行。

countDownLatch和CyclicBarrier的区别

  1. countDownLatch是一个线程等一组线程执行完成之后才执行, cyclicBarrier是一组线程互相等待至某个状态之后,同时执行。
  2. countDownLatch不能复用,cyclicBarrier可以重用。

16、锁降级

锁降级是指将写锁降级为读锁,这个过程就是当前线程已经获取到写锁的时候,再获取到读锁,随后释放写锁的过程,这么做的目的为的就是保证数据的可见性。

17、逃逸分析

  1. 逃逸分析就是分析对象的动态作用域,当一个对象在方法中被定义后,他可能被外部方法所引用,作为参数传递到其他方法中,成为方法逃逸,赋值给类变量或者可以被其他线程访问的实例变量成为线程逃逸。
  2. 使用逃逸分析,编译器可以对代码做优化。比如:同步省略(锁消除),将堆分配转化为栈分配,标量替换。
  3. 使用逃逸分析的缺点,没法保证逃逸分析的性能一定高于其他性能。极端的话经过逃逸分析后,所有的对象都逃逸了,那么逃逸分析的过程就浪费了。

tencent.jpg

Guess you like

Origin www.cnblogs.com/clawhub/p/12064436.html