Java 并发编程

简介: 面试

16、什么是并发容器的实现?

何为同步容器:可以简单地理解为通过 synchronized 来实现同步的容器,如果有 多个线程调用同步容器的方法,它们将会串行执行。比如 Vector,Hashtable, 以及 Collections.synchronizedSet,synchronizedList 等方法返回的容器。 可以通过查看 Vector,Hashtable 等这些同步容器的实现代码,可以看到这些容 器实现线程安全的方式就是将它们的状态封装起来,并在需要同步的方法上加上 关键字 synchronized。 并发容器使用了与同步容器完全不同的加锁策略来提供更高的并发性和伸缩性, 例如在 ConcurrentHashMap 中采用了一种粒度更细的加锁机制,可以称为分段 锁,在这种锁机制下,允许任意数量的读线程并发地访问 map,并且执行读操作 的线程和写操作的线程也可以并发的访问 map,同时允许一定数量的写操作线程 并发地修改 map,所以它可以在并发环境下实现更高的吞吐量。

17、多线程同步和互斥有几种实现方法,都是什么?

线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程 的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。 线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性。当有若 干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它 要使用该资源的线程必须等待,直到占用资源者释放该资源。

线程互斥可以看成 是一种特殊的线程同步。 线程间的同步方法大体可分为两类:用户模式和内核模式。顾名思义,内核模式 就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态, 而用户模式就是不需要切换到内核态,只在用户态完成操作。 用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。内核模 式下的方法有:事件,信号量,互斥量。

18、什么是竞争条件?你怎样发现和解决竞争?

当多个进程都企图对共享数据进行某种处理,而最后的结果又取决于进程运行的 顺序时,则我们认为这发生了竞争条件(race condition)。

19、为什么我们调用 start()方法时会执行 run()方法,为什么我们不能直接调用 run()方法?

当你调用 start()方法时你将创建新的线程,并且执行在 run()方法里的代码。 但是如果你直接调用 run()方法,它不会创建新的线程也不会执行调用线程的代码, 只会把 run 方法当作普通方法去执行。

20、Java 中你怎样唤醒一个阻塞的线程?

在 Java 发展史上曾经使用 suspend()、resume()方法对于线程进行阻塞唤醒,但 随之出现很多问题,比较典型的还是死锁问题。 解决方案可以使用以对象为目标的阻塞,即利用 Object 类的 wait()和 notify()方 法实现线程阻塞。 首先,wait、notify 方法是针对对象的,调用任意对象的 wait()方法都将导致线程 阻塞,阻塞的同时也将释放该对象的锁,相应地,调用任意对象的 notify()方法则 将随机解除该对象阻塞的线程,但它需要重新获取改对象的锁,直到获取成功才 能往下执行;其次,wait、notify 方法必须在 synchronized 块或方法中被调用, 并且要保证同步块或方法的锁对象与调用 wait、notify 方法的对象是同一个,如 此一来在调用 wait 之前当前线程就已经成功获取某对象的锁,执行 wait 阻塞后当 前线程就将之前获取的对象锁释放。

相关文章
|
2月前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####
|
1月前
|
安全 Java 程序员
深入理解Java内存模型与并发编程####
本文旨在探讨Java内存模型(JMM)的复杂性及其对并发编程的影响,不同于传统的摘要形式,本文将以一个实际案例为引子,逐步揭示JMM的核心概念,包括原子性、可见性、有序性,以及这些特性在多线程环境下的具体表现。通过对比分析不同并发工具类的应用,如synchronized、volatile关键字、Lock接口及其实现等,本文将展示如何在实践中有效利用JMM来设计高效且安全的并发程序。最后,还将简要介绍Java 8及更高版本中引入的新特性,如StampedLock,以及它们如何进一步优化多线程编程模型。 ####
37 0
|
1月前
|
Java 程序员
Java编程中的异常处理:从基础到高级
在Java的世界中,异常处理是代码健壮性的守护神。本文将带你从异常的基本概念出发,逐步深入到高级用法,探索如何优雅地处理程序中的错误和异常情况。通过实际案例,我们将一起学习如何编写更可靠、更易于维护的Java代码。准备好了吗?让我们一起踏上这段旅程,解锁Java异常处理的秘密!
|
29天前
|
存储 缓存 Java
Java 并发编程——volatile 关键字解析
本文介绍了Java线程中的`volatile`关键字及其与`synchronized`锁的区别。`volatile`保证了变量的可见性和一定的有序性,但不能保证原子性。它通过内存屏障实现,避免指令重排序,确保线程间数据一致。相比`synchronized`,`volatile`性能更优,适用于简单状态标记和某些特定场景,如单例模式中的双重检查锁定。文中还解释了Java内存模型的基本概念,包括主内存、工作内存及并发编程中的原子性、可见性和有序性。
Java 并发编程——volatile 关键字解析
|
1月前
|
算法 Java 调度
java并发编程中Monitor里的waitSet和EntryList都是做什么的
在Java并发编程中,Monitor内部包含两个重要队列:等待集(Wait Set)和入口列表(Entry List)。Wait Set用于线程的条件等待和协作,线程调用`wait()`后进入此集合,通过`notify()`或`notifyAll()`唤醒。Entry List则管理锁的竞争,未能获取锁的线程在此排队,等待锁释放后重新竞争。理解两者区别有助于设计高效的多线程程序。 - **Wait Set**:线程调用`wait()`后进入,等待条件满足被唤醒,需重新竞争锁。 - **Entry List**:多个线程竞争锁时,未获锁的线程在此排队,等待锁释放后获取锁继续执行。
66 12
|
29天前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
160 2
|
2月前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
|
2月前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
1月前
|
安全 算法 Java
Java多线程编程中的陷阱与最佳实践####
本文探讨了Java多线程编程中常见的陷阱,并介绍了如何通过最佳实践来避免这些问题。我们将从基础概念入手,逐步深入到具体的代码示例,帮助开发者更好地理解和应用多线程技术。无论是初学者还是有经验的开发者,都能从中获得有价值的见解和建议。 ####
|
1月前
|
Java 调度
Java中的多线程编程与并发控制
本文深入探讨了Java编程语言中多线程编程的基础知识和并发控制机制。文章首先介绍了多线程的基本概念,包括线程的定义、生命周期以及在Java中创建和管理线程的方法。接着,详细讲解了Java提供的同步机制,如synchronized关键字、wait()和notify()方法等,以及如何通过这些机制实现线程间的协调与通信。最后,本文还讨论了一些常见的并发问题,例如死锁、竞态条件等,并提供了相应的解决策略。
66 3