暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

尚硅谷周阳老师大厂面试题笔记

v587博客 2021-08-24
553

1、谈谈你对volatile的理解

答:volatile是java虚拟机提供的轻量级的同步机制。

      volatile保证可见性、不保证原子性、禁止指令重排序

2、谈谈JMM

答:JMM是java memory model,java内存模型。它是一种抽象的概念,并不真实存在。它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。

即:线程对变量的操作必须在工作内存中进行,首先将变量从主内存拷贝到自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存。

JMM对变量的可见性、有序性(禁止指令重排序)、原子性有相应规定。

3、CAS是什么?

compare and swap。比较并交换

AtomicInteger.compareAndSet

unsafe.compareAndSet

CAS依赖于Unsafe

它是一条CPU并发原语。

它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的。调用Unsafe类中的CAS方法,JVM会帮我们实现出CAS汇编指令。这是一种完全依赖于硬件的功能,通过它实现了原子操作。

CAS是一种系统原语,原语属于操作系统用语范畴,是由若干条指令组成的,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致问题。

乐观锁的实现方式

4、Unsafe

rt.jar中的类,使用native修饰的方法。基于该类可以直接操作特定内存的数据。

Unsaft类存在于sun.misc包中,其内部方法操作可以像C的指针一样直接操作内存。

Unsafe类中的方法都直接调用操作系统底层资源执行相应任务。

5、CAS的缺点:

循环时间长开销很大,只能保证一个共享变量的原子操作,会引发ABA问题

6、ABA问题

多版本问题,改过一次后改回原值。

尽管结果是一致的,但是过程不一定。

解决办法:使用原子引用,AtomicReference

7、原子引用,AtomicReference

compareAndSet(A,B) 保证只能修改一次

8、原子时间戳引用,AtomicStampedReference

中间有修改过,不可以cas修改

版本getStamp,最新值:getReference。


9.ArrayList

默认size是10,扩容一半5个。

ArrayList并发访问时候,会抛出java.util.ConcurrentModificationException

new Vector<>() 和 Collections.synchronizedList(new ArrayList<>());

CopyOnWriteArrayList


10.CopyOnWriteArrayList

volatile修饰数组,ReetrantLock修饰add方法。读写分离,写时候复制,原数组废弃。


11.HashSet

会抛出java.util.ConcurrentModificationException

Collections.synchronizedSet

CopyOnWriteArraySet,内部使用CopyOnWriteArrayList

底层是HashMap, key都是PRESENT

12.HashMap

会抛出java.util.ConcurrentModificationException

使用ConcurrentHashMap,或Collections.sychronizedMap

13.公平锁和非公平锁

ReetrantLock 是可重入锁。默认是非公平锁,可以构造器设置true,为公平锁。

公平锁,就是队列,先来后到。具体是:是指多个线程按照申请锁的顺序来获取锁,类似排队打饭,先来后到。

在并发环境中,每个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等待队列的第一个,就占有锁,否则就会加入到等待队列中,以后会按照FIFO的规则从队列中取到自己


非公平锁,插队。是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程优先获取锁在高并发的情况下,有可能会造成优先级反转或者饥饿现象。

非公平锁比较粗鲁,上来就直接尝试占有锁,如果尝试失败,就再采用类似公平锁那种方式。

14.可重入锁

锁:学校门栓,加锁和解锁。

可重入锁,就是递归锁,ReetrantLock和sychronized。外层函数获得锁,内层函数仍然能获取该锁的代码。

15.自旋锁

Unsafe类+CAS思想,获取锁的线程不会立即阻塞,而是采用循环的方式尝试获取锁。这样的好处是减少线程上下文切换,缺点是循环消耗cpu

16.独占锁和共享锁

独占锁:指被锁一次只能被一个线程锁持有。对ReetrantLock和Synchronized而言都是独占锁。

共享锁:指该锁可被多个线程所持有。

对ReetrantReadWriteLock其读锁是共享锁,其写锁是独占锁。

读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的。

17.CountDownLatch 计数器

CountDownLatch countDownLatch  = new CountDownLatch6)

countDownLatch.countDown()

countDownLatch.await()

子线程中计数器n减少为0,主线程才可以继续

18.CyclicBarrier 循环屏障

到齐了再做。

集齐7颗龙珠召唤神龙。

让一组线程到达一个屏障,也可以叫做同步点时,被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await方法

CyclicBarrier cyclicBarrier  = new CyclicBarrier (7,()->func{});

cyclicBarrier .await()

19.Semaphore 信号灯

增车位。

作用:一个是共享资源互斥访问,一个是并发线程数的控制

默认非公平锁

Semaphore semaphore = new Semaphore(3,nonfair) ;//3个停车位

semaphore.acquire() 抢车位

semaphore.release()




文章转载自v587博客,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论