【费曼系列-5】使用费曼学习法来掌握Java并发编程

费曼学习法的精髓在于用自己的语言把学习的知识给他人讲懂

下面有一些问题,并附有答案和对该知识点的详解,如果你能用自己的语言把该问题讲解清楚,那恭喜你,该知识点你掌握了!


1. JUC包中常见的类都有哪些?

JUC包中有很多并发编程需要的工具类,可按照以下几种类别进行梳理:

  • ThreadLocal,ThreadLocalRandom
  • 原子操作类:AtomicInteger等
  • 锁:ReentrantLock,ReentrantReadWriteLock
  • 同步器:Semaphore,CoundDownLatch,CyclicBarrier
  • 同步Map:ConcurrentHashMap
  • 同步List:CopyOnWriteArrayList
  • 同步队列:ConcurrentLinkedQueue,LinkedBlockingQueue,ArrayBlockingQueue

详细原理戳这里: JUC包中常用工具类的简单介绍和使用说明(上)

2. Java的synchronized关键字怎么用?其实现原理是什么?

synchronized关键字可以使线程对临界区互斥访问,synchronized可以修饰类静态方法、类普通方法和普通代码块。当线程执行到synchronized修饰的代码时,其首先要去获取一个内部锁,只有拿到锁之后才能访问临界区,拿不到锁的线程就会挂起等待锁的释放。

synchronized能够进行线程同步的基础是:Java中的每一个对象都可以当作一个锁。每一个对象都有一个与之关联的Monitor,在对象头的Mark Word中记录了这个Monitor的地址,JVM内部对线程的挂起和唤醒是通过这个Monitor实现的。

详细原理戳这里: 详解Java中synchronized的实现原理

3. Java的synchronized关键字和Lock有什么区别?

synchronized是java的关键字,是jvm层面的;Lock是一个接口,具体实现类有ReentrantLock。如果有可中断、公平锁、控制锁时长等需求,必须用Lock,但synchronized语法更简洁。使用Lock要记得在finally中释放锁,不然容易造成线程死锁;而采用synchronized不需要用户去手动释放锁

详细原理戳这里: 详解Java中synchronized的实现原理

4. Java并发中的CAS操作是什么?

CAS,Compare And Swap,是乐观锁解决冲突的一种方式。CAS操作有三个参数,内存地址V,期待值A,修改值B,只有当V的值等于A时,才将V的值修改为B,否则不做操作。Java中的CAS操作是Unsafe类中相应的函数直接被虚拟机生成及其相关的CAS原子指令来实现的。

详细原理戳这里: 当我谈CAS时,我谈些什么

5. Java并发中的CAS操作有什么缺点?

CAS操作有三个缺点:

  • 循环耗时问题,如果CAS长期不成功,则很消耗CPU时间
  • 只能操作一个原子变量
  • ABA问题,当一个线程的期待值是A,其它线程把值改为B又改回A时,该线程无法直到值已被修改。

详细原理戳这里: 当我谈CAS时,我谈些什么

6. Java中的volatile有什么作用?

volatile主要提供内存可见性的保证,也就是说:

  • 当对一个volatile变量进行写操作时,JMM会把该线程中的共享变量刷新到主内存中去
  • 当对一个volatile变量进行读操作时,JMM会把当前线程的本地内存中的变量置为无效,然后从主内存中读取最新值。

但需要注意的是,volatile不能保证复合操作的原子性,例如a++等操作,在使用volatile变量来保证线程安全时要特别注意这一点。

详细原理戳这里: Java中的volatile简介

7. Java中的volatile和synchronized有什么区别?

volatile修饰变量,而synchronized修饰方法和代码块。volatile只能保证内存可见性,不能保证原子性,而synchronized都可以保证。

从功能上讲,volatile的功能只是synchronized的一个子集,但volatile不需要阻塞线程,因此性能更好一些。

详细原理戳这里: Java中的volatile简介详解Java中synchronized的实现原理

8. Java中的ThreadLocal的实现原理是什么?

当多线程访问ThreadLocal共享变量时,会在线程的本地内存中产生一个副本,以后对该共享变量的操作都是对本地内存中的副本变量操作,因此解决了多线程竞争问题。

ThreadLocal的实现原理:Thread类中有一个threadLocals的成员变量,是一个Map,其key为ThreadLocal的弱引用,其value为set方法传入的值。当我们使用ThreadLocal中的set方法时,首先获取当前线程的threadLocals哈希表,再以当前对象的this引用为key进行set操作。

详细原理戳这里: 详解JUC中ThreadLocal的实现原理

9. Java中的ThreadLocal有什么缺点?

ThreadLocal的缺点有二,第一是使用不当容易造成内存泄漏,第二是处理哈希冲突时使用线性探测法,在极端情况下性能会退化到O(n)。

关于内存泄漏,使用ThreadLocal时,如果没及时调用remove方法,可能会产生内存泄漏。ThreadLocalMap中key为ThreadLocal的弱引用,在没有其它强引用的情况下遇到GC会被清除掉,但ThreadLocalMap的value仍然是强引用,这时就会出现ThreadLocalMap中key为null但value不为null的情况,此时再调用remove方法已无法清除掉value的强引用,而只要线程存在则ThreadLocalMap就一直存在则该value就永远无法被GC,因此就产生了内存泄漏。

详细原理戳这里: 详解JUC中ThreadLocal的实现原理

10. JUC中的ConcurrentHashMap是如何实现的?

总的来说,ConcurrentHashMap的实现使用了减小锁粒度以减少并发冲突的编程思想。

JDK1.7中的ConcurrentHashMap底层使用Segment数组实现,Segment继承自ReentrantLock,每个Segment管理若干个位桶,每个位桶中的Entry使用链表法来解决哈希冲突。因此,只要多个线程操作的不是同一个Segment,便不会引起竞争。

JDK1.8中的ConcurrentHashMap底层使用数组+链表+红黑树实现,利用synchronized和CAS来进行并发控制,看起来就像是一个经过优化且并发安全的HashMap。锁的粒度是每一个位桶,因此只要多线程操作的不是同一个位桶,便不会引起竞争。它首先使用无锁操作CAS插入头结点,如果插入失败,说明已经有别的线程插入头结点了,再次循环进行操作。如果头结点已经存在,则通过synchronized获得头结点锁,进行后续的操作,性能比segment分段锁又再次提升。

详细原理戳这里: 简析JUC中ConcurrentHashMap的实现原理

11. JUC中的AQS的实现原理是什么?

AQS是一个用来构建锁和同步器的框架,它是一个抽象类,使用了模板方法模式。继承自AQS的自定义同步器在实现时只需要实现共享资源的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在底层实现好了。

AQS底层主要基于一个volatile的state变量和双向队列实现。state变量一般代表共享资源,其在不同的应用场景下具有不同的含义,AQS通过CAS来操作state变量,获取成功则设置当前线程为工作线程,获取失败则把当前线程封装成一个节点插入双向队列并挂起等待,当共享资源被释放时,则再从队列里取一个线程进行唤醒。其中,入队出队操作也是通过CAS来操作队列头尾节点实现的,线程的挂起和唤醒是通过LockSupport工具类来实现的。

详细原理戳这里: 详解JUC中的基础组件AQS

12. JUC中的LockSupport是做什么用的?

LockSupport用来挂起和唤醒线程,其底层基于Unsafe类的native方法实现,其核心方法有park和unpark:

  • park:park方法用来挂起线程。若调用park的线程持有一个许可,则park立即返回;若不持有,则该线程挂起。
  • unpark:unpark方法用来唤醒线程。若调用unpark的线程没有持有许可,则令其持有;若该线程被挂起,则将其唤醒。

详细原理戳这里: 简析JUC中的LockSupport

13. JUC中的LockSupport和wait/notify方法有什么区别?

  • wait必须在synchronized代码块中执行,park可以在任何地方执行
  • wait必须捕获中断异常,而park不需要
  • wait不带有超时功能,而parkNanos等方法可以有
  • notify不能指定唤醒的线程,而park可以
  • 如果在wait之前执行了notify,会抛出IllegalMonitorStateException异常;但在park之前执行了unpark,不会有影响,park会直接返回

详细原理戳这里: 简析JUC中的LockSupport

14. Java中ThreadLocal的应用场景是什么?

当一个共享变量的作用并不是用来在线程间通信,而是线程都要使用这个共享变量来完成自己内部的工作时,就可以使用ThreadLocal,从而能避免并发竞争。例如,当多个线程使用同一个Random时,会出现对随机数种子的竞争从而造成性能下降,故产生了ThreadLocalRandom这个类来解决这个问题。

详细原理戳这里: 详解JUC中ThreadLocal的实现原理

【长期更新中......】

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,869评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,716评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,223评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,047评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,089评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,839评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,516评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,410评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,920评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,052评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,179评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,868评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,522评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,070评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,186评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,487评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,162评论 2 356

推荐阅读更多精彩内容