您的位置:首页 > 文旅 > 旅游 > 移动应用开发课程_网站建设价格情况_营销网站建设服务_黑龙江最新疫情通报

移动应用开发课程_网站建设价格情况_营销网站建设服务_黑龙江最新疫情通报

2024/12/23 8:56:58 来源:https://blog.csdn.net/csdn3043663729/article/details/144185672  浏览:    关键词:移动应用开发课程_网站建设价格情况_营销网站建设服务_黑龙江最新疫情通报
移动应用开发课程_网站建设价格情况_营销网站建设服务_黑龙江最新疫情通报

 其他资料

每日速记10道java面试题01-CSDN博客

每日速记10道java面试题02-CSDN博客

每日速记10道java面试题03-CSDN博客

每日速记10道java面试题04-CSDN博客

每日速记10道java面试题05-CSDN博客

每日速记10道java面试题06-CSDN博客

每日速记10道java面试题07-CSDN博客

每日速记10道java面试题08-CSDN博客

目录

1.ThreadLocal的原理(简易版)

2.线程中blocked和waiting有什么区别?

3.怎么保证多线程安全?

4.Java中有哪些常用的锁,在什么场景下使用?

5.怎么理解可重入锁?

6.Java中想实现一个乐观锁,都有哪些方式?

7.java中volatile关键字有什么作用?

8.volatile可以替代synchronized吗?

9.什么是java中的ABA问题?


1.ThreadLocal的原理(简易版)

Thread Local内部有个map集合,map里面存放了一系列的key/value,key值保存Thread Local本身,当调用Thread Local的get方法时,首先回去map集合中找有无当前Thread Local的key,有的话直接返回,没有就进行创建并放入,当调用set方法时,就会在map中存储对应的键值对,当调用remove时,则从map中移除与该Thread Local对象相关的键值对。

2.线程中blocked和waiting有什么区别?

触发条件:线程进入阻塞状态通常是想要获取一个对象的锁,但该锁已经被另一个线程占有,这时线程就会进入阻塞状态直到锁可用。而进入等待状态一般是等待另一个线程进行某些操作,这时线程不会占用CPU资源不会参与锁的竞争

唤醒机制:当一个线程阻塞等待锁时,一旦锁释放,线程就会抢占锁并从阻塞状态变化为运行状态。而线程进入等待状态时需要被显式唤醒,比如线程调用了object.wait方法,就需要等待其他线程的notify或者notifyAll来唤醒。

延伸→notify 和 notifyAll 的区别?

回答:

区别在于:

  1. notify:唤醒一个线程,其他线程依旧处于wait的等待唤醒状态
  2. notifyAll:所有线程退出wait状态,开始竞争锁

延伸→notify选择哪个线程?

notify的源码注释提到说notify选择唤醒的线程是任意的,但是依赖于具体实现的jvm,目前比较流行的jvm实现是hotspot,hotspot是采用队列也就是先进先出的顺序唤醒。

3.怎么保证多线程安全?

1)synchronized关键字:可以使用synchronized关键字来同步代码块或方法,确保同一时刻只有一个线程可以访问这些代码。(实现原理见→   每日速记10道java面试题06-CSDN博客)

2)volatile关键字:volatile关键字用于变量,确保所有线程看到的是该变量最新的值。(见问题7)

3)原子类Java并发库提供了原子类,比如atomic Integeratomic Long可以用于更新基本数据类型的变量而无需额外的同步

4)线程局部变量:ThreadLocal类可以为每个线程提供变量副本,这样每个线程都有自己的变量,消除了竞争条件。(实现原理见问题1)

5)使用并发集合:使用ConcurrentHashMap等一些实现了线程安全逻辑的集合。

4.Java中有哪些常用的锁,在什么场景下使用?

  1. 内置锁:Java中的synchronized关键字是内置锁机制的基础,当线程进入同步代码块或方法时,就会获取锁,离开代码块时,锁就会被释放。其他线程想要获取该锁时会被阻塞直到锁释放
     
  2. 读写锁:允许多个读者访问共享资源,但只允许一个写者,一般适用于读操作远多于写操作的场景。
     
  3. 乐观锁悲观锁:悲观锁是指当其他线程访问数据前就锁定资源不让进synchronized就是悲观锁的例子。乐观锁通常不锁定资源,而是在更新数据时检查数据是否被其他线程修改修改了就不允许更新,没修改就可以更新,通常使用版本号时间戳来实现乐观锁。(怎么实现乐观锁? 问题6)
     
  4.  自旋锁:线程在等待锁时循环检查锁是否可用而不是直接放弃CPU阻塞等待。适用在所等待时间很短的场景,可以提高性能,但过度自旋会浪费CPU

5.怎么理解可重入锁?

可重入锁就是同一个线程在获取了锁之后,再次重复获取该锁可以成功获取且不会导致死锁等其他问题。

ReentrantLock实现可重入锁是基于内部的计数器。(具体来说一个state变量+两个队列具体看以下文章:每日速记10道java面试题06-CSDN博客)

当一个线程获取锁时,计数器+1,同一个线程重复获取同一个锁,计数器会+1,当线程释放锁时,计数器-1,只有当计数器减到0时,才会彻底释放锁。

延伸→synchronized能否作为可重入锁?

支持重入的,具体是由底层的线程IDstatus实现的,当一个线程成功获取锁时,会记录该线程的线程ID,之后每次线程尝试获取锁,会比较线程ID如果相同则允许获取status+1,在释放锁时,每一次退出方法status-1,直到status为0,锁才完全释放

6.Java中想实现一个乐观锁,都有哪些方式?

版本号控制:增加一个版本号字段记录数据更新时候的版本每次更新成功时递增版本号,在更新的时候判断当前版本号是否与更新前版本号一致是的话则更新不是的话就不更新

时间戳:使用时间戳记录数据更新时间,每次更新数据时,比较时间戳,如果当前时间戳大于数据时间戳,则说明数据在更新前已经被其他线程更新了,这时就停止更新操作。

7.java中volatile关键字有什么作用?

保证变量第所有线程的可见性:如果一个变量被声明为volatile时,这时对该变量的所有修改都会被其他线程看到

禁止指令重排序优化

写写屏障:在对volatile变量执行写操作时,会插入一个写屏障,确保之前的一切的普通写操作已完成,不会在写完volatile变量之后又写

读写屏障执行读操作,会插入一个读屏障,保证volatile读之后的其他普通读操作不会被放到volatile读之前执行,保证读到的数据是最新的。

写读屏障:这是最重要的一个屏障,在volatile写后和volatile读前,确保写前不读,读后不写。

8.volatile可以替代synchronized吗?

不可以,volatile关键字可以保证可见性,但不能保证原子性,因此不能替代synchronized。Volatile关键字用来修饰变量,使得变量在一个线程修改可以被其他线程看到这次修改,也就是他的可见性。但是它不能保证原子性,所以如果要保证线程安全的话,最好还是使用synchronized关键字。(synchronized是如何保证原子性的?→每日速记10道java面试题06-CSDN博客)

9.什么是java中的ABA问题?

CAS里面一个线程将一个数据从A变成了B,又变回了A,这时候,另一个线程会认为这个数据没有发生变化,继续进行操作,可能导致错误。其实现在的A已经不是当初的A了。

解决办法:加版本号或者时间戳
修改数据的时候,给数据添加一个版本号;在进行CAS操作的时候,除了比较内存中的实际值与期望值外,还比较版本号。版本号相同就修改,否则失败重试。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com