《Java并发编程》
- 自旋锁与互斥锁
两者非常类似,只是调度策略的不同。对于独占资源的访问,互斥锁在获得锁之前将一直处于休眠状态,自旋锁则是不断的自我循环来等待锁。对于线程切换没有损失,但消耗CPU,等待过长影响系统性能。
- 并发包中的信号量与有界阻塞容器
Semaphore用来控制对某种资源的访问数量,可以用来实现资源池化访问,也可以将任何一种容器变成有界阻塞容器。
- 线程的关闭
大多数时候使用原生线程都是等到运行结束而自动关闭,然而有时候也需要提前结束线程,比如用户取消了操作。但Java没有提供任何机制来安全地终止线程。仅提供了中断(Interruption),这是一种协作机制,能够使一个线程终止另一个线程(Thread.stop和suspend存在缺陷,避免使用)。
解决方案有:非阻塞情况下使用volatile类型的变量来做标记,阻塞框架又存在可中断和不可中断,可中断调用阻塞框架中断方法,例如对阻塞队列的操作。处理好中断异常,保证数据完整性。不可中断的阻塞如IO的操作或者等待获得锁而阻塞,在取消方法中先关闭IO,或者调用Lock类的lockInterruptibly。
- 线程饥饿死锁
在线程池中,任务依赖其他任务,那么可能产生死锁。在单线程Executor中,一个任务将另一个任务提交到同一个Executor,并且等待这个被提交任务的结果,会死锁。
- 线程池大小
线程池过大,大量的线程将在相对很少的CPU和内存资源上发生竞争,导致更高的内存占用量。线程池过小导致处理器空闲,减低吞吐率。
- synchronized与ReentrantLock
两者jvm层语义一致,Java 6及更高版本两者效率差别已经不是很大,Lock具有公平与非公平两种选择,除本身特性之外,非公平锁吞吐率高于公平。其原因是恢复一个被挂起的线程与该线程真正开始运行之间存在较大延时。Lock具有定时锁等待,可中断锁等待,非结构化加锁。