当线程需要同时持有多个锁时,有可能产生死锁。考虑如下情形:线程 A 当前持有互斥所锁 lock1,线程 B 当前持有互斥锁 lock2。接下来,当线程 A 仍然持有 lock1 时,它试图获取 lock2,因为线程 B 正持有 lock2,因此线程 A 会阻塞等待线程 B 对 lock2 的释放。
在 JDK 的 Collection 中我们时常会看到类似于这样的话:例如,ArrayList:注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。
在前面 LZ 详细介绍了 HashMap 、HashTable 、TreeMap 的实现方法,从数据结构、实现原理、源码分析三个方面进行阐述,对这个三个类应该有了比较清晰的了解,下面 LZ 就 Map 做一个简单的总结。
前面 LZ 已经充分介绍了有关于 List 接口的大部分知识,如 ArrayList、LinkedList、Vector、Stack,通过这几个知识点可以对 List 接口有了比较深的了解了。只有通过归纳总结的知识才是你的知识。所以下面 LZ 就 List 接口做一个总结。
在我们编程过程中如果需要执行一些简单的定时任务,无须做复杂的控制,我们可以考虑使用 JDK 中的 Timer 定时任务来实现。下面 LZ 就其原理、实例以及 Timer 缺陷三个方面来解析 Java Timer 定时器。一、简介在 Java 中一个完整定时任务需要由 Timer、TimerTask 两个类来配合完成。 API 中是这样定义他们的,Timer:一种工具,线程用其安排以后在后台线程中执行的任务。
阿姆达尔定律可以用来计算处理器平行运算之后效率提升的能力。阿姆达尔定律因 Gene Amdal 在 1967 年提出这个定律而得名。绝大多数使用并行或并发系统的开发者有一种并发或并行可能会带来提速的感觉,甚至不知道阿姆达尔定律。不管怎样,了解阿姆达尔定律还是有用的。我会首先以算术的方式介绍阿姆达尔定律定律,然后再用图表演示一下。
CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术。简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替换当前变量的值。这听起来可能有一点复杂但是实际上你理解之后发现很简单,接下来,让我们跟深入的了解一下这项技术。
线程池(Thread Pool)对于限制应用程序中同一时刻运行的线程数很有用。因为每启动一个新线程都会有相应的性能开销,每个线程都需要给栈分配一些内存等等。我们可以把并发执行的任务传递给一个线程池,来替代为每个并发执行的任务都启动一个新的线程。只要池里有空闲的线程,任务就会分配给一个线程执行。
Semaphore(信号量)是一个线程同步结构,用于在线程间传递信号,以避免出现信号丢失(译者注:下文会具体介绍),或者像锁一样用于保护一个关键区域。自从 5.0 开始,jdk 在 java.util.concurrent 包里提供了 Semaphore 的官方实现,因此大家不需要自己去实现 Semaphore。
重入锁死与死锁和嵌套管程锁死非常相似。锁 和读写锁两篇文章中都有涉及到重入锁死的问题。当一个线程重新获取锁,读写锁或其他不可重入的同步器时,就可能发生重入锁死。可重入的意思是线程可以重复获得它已经持有的锁。Java 的 synchronized 块是可重入的。
相比 Java 中的锁(Locks in Java)里 Lock 实现,读写锁更复杂一些。假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。
死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁。死锁通常发生在多个线程同时但以不同的顺序请求同一组锁的时候。例如,如果线程 1 锁住了 A,然后尝试对 B 进行加锁,同时线程 2 已经锁住了 B,接着尝试对 A 进行加锁,这时死锁就发生了。线程 1 永远得不到 B,线程 2 也永远得不到 A,并且它们永远也不会知道发生了这样的事情。
Java 同步块(synchronized block)用来标记方法或者代码块是同步的。Java 同步块用来避免竞争。本文介绍以下内容:Java 同步关键字(synchronzied)实例方法同步静态方法同步实例方法中同步块静态方法中同步块Java 同步示例Java 同步关键字(synchronized)Java 中的同步块用 synchronized 标记。同步块在 Java 中是同步在某个对象上。
从一个单线程的应用到一个多线程的应用并不仅仅带来好处,它也会有一些代价。不要仅仅为了使用多线程而使用多线程。而应该明确在使用多线程时能多来的好处比所付出的代价大的时候,才使用多线程。如果存在疑问,应该尝试测量一下应用程序的性能和响应能力,而不只是猜测。设计更复杂虽然有一些多线程应用程序比单线程的应用程序要简单,但其他的一般都更复杂。
尽管面临很多挑战,多线程有一些优点使得它一直被使用。这些优点是:资源利用率更好程序设计在某些情况下更简单程序响应更快资源利用率更好想象一下,一个应用程序需要从本地文件系统中读取和处理文件的情景。比方说,从磁盘读取一个文件需要 5 秒,处理一个文件需要 2 秒。
在过去单 CPU 时代,单任务在一个时间点只能执行单一程序。之后发展到多任务阶段,计算机能在同一时间点并行执行多任务或多进程。虽然并不是真正意义上的“同一时间点”,而是多个任务或进程共享一个 CPU,并交由操作系统来完成多任务间对 CPU 的运行切换,以使得每个任务都有机会获得一定的时间片运行。
Java 反射机制可以让我们在编译期(Compile Time)之外的运行期(Runtime)检查类,接口,变量以及方法的信息。反射还可以让我们在运行期实例化对象,调用方法,通过调用 get/set 方法获取变量的值。Java 反射机制功能强大而且非常实用。
个人日常学习之余记下的笔记,仅供参考。
关注时代Java