多线程相关面试

synchronized

锁升级过程

参考:https://blog.csdn.net/qq_41125219/article/details/121739597

先讲一下对象的内存布局:对象头,实例数据,对齐填充
对象头又分两部分:MarkWord和类型指针(对象数据哪个类的实例)。我们锁升级的过程都会涉及对对象头的一系列操作。

  • 无锁:这是没有开启偏向锁的时候的状态,在JDK1.6之后偏向锁的默认开启的(但是有一个偏向延迟,需要在JVM启动4秒之后才能开启(JVM启动的时候需要多个线程去竞争资源),这个可以通过JVM参数进行设置,同时是否开启偏向锁也可以通过JVM参数设置)。这个时候MarkWord里的偏向锁位和锁标志位分别是0和01。
  • 偏向锁:当某个线访问同步代码块获取锁时,不再去关联monitor对象,而是使用CAS将线程ID设置到对象头中的markword中,并且虚拟机栈中的锁记录也会存储锁偏向的线程ID,当需要再次获取锁的时候只需要对比markword中的线程ID是否相同如果相同就可以直接获取锁,如果不相同说明发生了锁竞争,这个时候会升级为轻量级锁。
  • 轻量级锁:当有多个线程竞争锁的时候会升级为轻量级锁
  • 重量级锁:当线程枪锁做CAS自旋次数超过10次或者线程等待的数量超过cpu核心数的1/2,升级为重量级锁

ThreadLoacl

概念

让没有线程拥有自己的本地变量,避免多线程并发访问同一资源的问题

原理

每个给一个Thread内部都有一个ThreadLocalMap类型的成员变量。这个ThreadLocalMap是一个key,value的结构。它以ThreadLoacal作为key,以Ojbect类型的对象作为value。这个对象也就是我们ThreadLocal里面set方法set进去的对象。看ThreadLocal的set方法的源码你会发现,它其实只是传递了参数。它会在方法里获取Thread线程对象,然后通过Thread类去获取ThreadLocalMap。

内存泄漏

ThreadLocalMap的key ThreadLocal为弱应用,value为强引用,这就导致在垃圾回收的时候key被清楚掉了,value却还在,这样就是内存泄漏,长期下去就会导致内存溢出。jdk.1.8之后就考虑到了这样的问题,在我们set和get的时候,它会把key为null的记录清楚调。当然我们最后是调用一下它的remove方法手动去清除。

使用场景

  • 线程不安全的SimpleDateFormat
  • 一些框架底层的一些实现,例如Spring框架在事物开始的时候会为每一个线程绑定一个jdb connection,实现事物的隔离。

AQS

AQS 用来构建锁和同步器的框架。核心思想是:如果请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果当前被请求的共享资源被占用,那就需要一套线程阻塞等待以及被唤醒时锁分配的机制。这个机制是用CLH队列(虚拟的的双向队列)锁实现的,简单理解就是暂时获取不到锁的线程加入到队列中。
实际项目中我配合线程池用过CountDownLatch。场景大概是这样的,我们定时任务同步元器件的时候有的时候会出现外贸和国内不一致的情况:例如库存,描述信息,元器件上下架状态信息等。当时就是做了一个补偿机制,提供一个拉去的按钮,如果发现出现不一致,可以通过手动批量的去拉去元器件信息。这个拉取操作呢设计到调用五其他服务的接口。当时是通过同步的方式挨个去调,但是发现性能上存在问题,如果是选择的元器件比较多的话响应时间比较久大概十多秒吧。快乐五倍。所以当时就考虑改一个方案通过多线程异步的方式去调。并且我又希望等所有线程执行完之后再返回前段处理成功。所以这个时候我就用到了countdownlatch
设置count数为5的countDownLatch对象,每执行完一个线程count-1。并调用await方法。

如何让线程顺序执行

参考:https://www.cnblogs.com/wenjunwei/p/10573289.html
[1] 使用线程的join方法:主线程要等子线程执行完后再执行
[2] 使用主线程的join方法
[3] 使用线程的wait方法
[4] 使用线程的线程池方法
[5] 使用线程的Condition(条件变量)方法
[6] 使用线程的CountDownLatch(倒计数)方法
[7] 使用线程的CyclicBarrier(回环栅栏)方法
[8] 使用线程的Semaphore(信号量)方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值