Java面试题-并发篇十六

  • 日期:07-14
  • 点击:(1945)

pp王者电子官网

669a5e80-8557-468b-a714-27f16fa78c2d

161,什么是Java内存模型?

Java内存模型指定并指导Java程序在不同的内存体系结构,CPU和操作系统之间确定性地运行。在多线程的情况下尤其重要。 Java内存模型对一个线程所做的更改可以由其他线程保证,并且它们是预先存在的。这种关系定义了规则,使程序员更清楚地了解并发编程。例如,先前的关系确保:

线程中的代码可以按顺序执行,称为程序顺序规则。

对于相同的锁,解锁操作必须在该时间之后发生的另一个锁定操作之前发生,也称为管道锁定规则。

先前对volatile的写操作在下一个易失性读操作之前称为volatile变量规则。

在线程的start()调用之后,线程内的任何操作都必须被称为线程启动规则。

线程的所有操作在线程终止之前终止规则。

在构造对象之后,必须将对象的最终化称为对象终止规则。

及物

可以将更多介绍转移到并发编程网络:

(深入理解java内存模型系列:

162,Java中断和isInterruptedd方法的区别?

interrupt()和isInterrupted()之间的主要区别在于前者清除中断状态而后者不清除。 Java多线程中断机制使用内部标识符实现。调用Thread.interrupt()来中断线程将中断标志设置为true。当中断线程调用静态方法Thread.interrupted()来检查中断状态时,中断状态被清除。

非静态方法isInterrupted()用于查询其他线程的中断状态,不会更改中断状态标志。简单地说,任何抛出InterruptedException的方法都会清除中断状态。在任何情况下,一个线程的中断状态可能被调用中断的其他线程改变。

163. Java中的同步集合和并发集合之间有什么区别?

同步和并发集合都为多线程和并发提供了合适的线程安全集合,但并发集合更具可伸缩性。在Java 1.5之前,程序员只使用同步集合并在多线程并发时引起争用,这阻碍了系统的可伸缩性。 Java5引入了ConcurrentHashMap等并发集合,它不仅提供了线程安全性,还通过锁定分离和内部分区等现代技术提高了可伸缩性。

无论是同步集合还是并发集合,它们都支持线程安全。它们之间的主要区别在于性能和可伸缩性,以及它们如何实现线程安全性。

同步HashMap,Hashtable,HashSet,Vector,ArrayList比它们的并发实现(ConcurrentHashMap,CopyOnWriteArrayList,CopyOnWriteHashSet)慢得多。这种缓慢的主要原因是锁定,同步集合将锁定整个Map或List,而并发集合则不会。并发集合通过使用锁定剥离等先进和成熟的技术来实现线程安全。

例如,ConcurrentHashMap将整个Map分成几个部分,仅锁定相关部分,并允许多个线程访问其他未锁定部分。

类似地,CopyOnWriteArrayList允许多个线程以非同步方式读取,并且当线程写入时,它将整个List的副本复制到它。

使用并发集合,这比使用同步集合更具可伸缩性。

164,什么是线程池?为什么要用它?

创建线程需要昂贵的资源和时间。如果创建了任务,则响应时间将更长,并且进程可以创建的线程数量有限。为了避免这些问题,创建了几个线程来响应程序启动时的处理。它们被称为线程池,内部的线程称为工作线程。从JDK 1.5开始,Java API提供了一个Executor框架,允许您创建不同的线程池。例如,一个单线程池,一次一个任务;固定数量的线程池或缓存线程池(具有许多短期任务的程序的可扩展线程池)

线程池的作用是在调用线程时初始化一定数量的线程。线程结束时,检测到初始化的线程为空。如果没有线程,则当前运行中的线程数已达到最大值。如果不是,则指定要处理的新线程。

就像在餐馆吃饭一样,它从里面叫做服务员;但如果达到最大数量,则相当于服务员已经用尽,那么就没有办法,其他线程只会等到有新的“服务员”直到。

线程池的优点是它可以管理线程,存在高度的中心,使程序不会混乱,以确保系统不会由于资源不足而导致大量并发而挂起。

165,Java中的活锁和死锁有什么区别?

活锁:线程通常具有响应其他线程的活动。如果其他线程也响应另一个线程的活动,则可以发出生命锁。与死锁一样,发出生命锁的线程无法继续执行。但是,线程没有阻塞他们正忙着响应另一方而无法恢复工作。这相当于在走廊里见面的两个人:A想让B传到他的左边,B想让A走。可以看出他们互相阻挡了。一个靠在他的右侧,B靠在他的左侧,他们仍然相互阻挡。

死锁:两个或多个线程阻塞处于死锁状态的其他线程持有的锁。当多个线程以不同的顺序同时请求同一组锁时,通常会发生死锁。死锁可能导致程序挂起并无法完成任务。

166,如何避免死锁?

件:片段:资源一次只能由一个进程使用。Piece:当进程因资源请求而阻塞时,它会保留已获取的资源。片断:在结束用完之前,不能强行剥夺该过程获得的资源。Piece:在多个进程之间形成头部和尾部之间的循环等待资源关系。

避免死锁的三种技术:

锁定顺序(线程按特定顺序锁定)

锁定时间限制(当线程尝试获取锁定时,它会增加一定的时间限制。如果超出时间限制,则会放弃锁定请求并释放它拥有的锁定)

死锁检测

(僵局的原因以及如何避免更深入地了解此举:

167,notify()和notifyAll()有什么区别?

1,notify()和notifyAll()是Object对象用于通知正在等待对象的线程的方法。

2,void notify():唤醒正在等待对象的线程。

3,void notifyAll():唤醒等待此对象的所有线程。

两者之间最大的区别是:

notifyAll导致等待对象上的通知的所有线程退出等待并等待对象的锁定。一旦物体被解锁,它们就会竞争。

通知他只是选择等待状态线程进行通知并使其获取对象的锁定,但不会警告其他线程也等待对象通知。当第一个线程完成运行时,将释放对象上的锁定。此时,如果对象不再使用notify语句,即使该对象已经空闲,等待该线程的另一个等待状态也不会获得该对象的通知,并继续等待该对象发出通知或者notifyAll,他们正在等待Notify或notifyAll,而不是锁定。

168,什么是ReentrantLock?

Java.util.concurrent.lock中的Lock框架是一个锁定的抽象,它允许将锁的实现实现为Java类而不是语言特性。这为Lock的多个实现留出了空间,Lock可能具有不同的调度算法,性能特征或锁定语义。 ReentrantLock类实现Lock,它具有与synchronized相同的并发和内存语义,但增加了锁定投票,定时锁定等待和可中断锁定等待等功能。此外,它在激烈争用的情况下提供更好的性能。 (换句话说,当许多线程想要访问共享资源时,JVM可以花更少的时间来调度线程并花更多的时间在执行线程上。)

重入锁是什么意思?简单来说,它有一个与锁相关的提取计数器。如果拥有锁的线程再次获得锁定,则获取计数器将增加1,然后需要释放锁定两次才能获得真正的释放。这模仿了synchronized的语义;如果线程进入受线程已拥有的监视器保护的同步块,则允许该线程继续。当线程退出第二个(或后续)同步块时,锁定不会被释放,只有线程退出。当锁进入受监视器保护的第一个同步块时,锁被释放。

169,读/写锁可用于哪些应用场景?

读写锁可用于“多读和无写”场景。读写锁同时支持多个读操作。写操作只能由一个线程执行

ReadWriteLock针对相对不频繁的数据结构写入进行了优化,但是有多个任务需要经常读取此数据结构。 ReadWriteLock允许您同时拥有多个读者,只要他们不尝试写入。如果写锁定已被另一个任务保留,则在释放写锁定之前,没有读取器可以访问它。

ReadWriteLock的性能改进主要取决于以下因素:

1.将读取数据的频率与被修改的频率进行比较的结果。

2,阅读和写作的时间

3.有多少线程竞争?

4,是否在多处理机器上运行

这是非常系统的。如果您需要了解该领域的更多信息,可以查看: