1. 线程安全性问题
死锁:哲学家就餐问题
假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。他们只能使用自己左右手边的那两只餐叉。
哲学家从来不交谈,这就很危险,可能产生死锁,每个哲学家都拿着左手的餐叉,永远都在等右边的餐叉(或者相反)。即使没有死锁,也有可能发生资源耗尽。
饥饿:餐厅排队问题
假设有个餐厅,此餐厅只开放一个窗口,现有个姑娘(线程)排队买东西。但是由于其他人(其他线程)没有素质,拼命插队,不停的插在姑娘之前买东西,以至于姑娘一直在排队,得不到资源,买不了东西。
活锁:二人过桥问题
活锁和死锁很像似。 只是活锁的状态可以发生改变。不过虽然状态可以改变,却没有实质的进展。
比如两个人在一个很宅的胡同里。 一次只能并排过两个人。 两人比较礼貌,都要给对方让路。 结果一起要么让到左边,要么让到右边,结果仍然是谁也过不去。 类似于原地踏步或者震荡状态。
活锁一般是由于对死锁的不正确处理引起的。由于处于死锁中的多个线程同时采取了行动。 而避免的方法也是只让一个线程释放资源。
2. 活跃性问题
一个并发应用程序能及时执行的能力称为活跃性。
A concurrent application’s ability to execute in a timely manner is known as its liveness.
安全性和活跃性之间存在某种制衡:
使用加锁机制来确保线程安全,但如果过度使用加锁,则可能导致锁顺序死锁(Lock-Ordering Deadlock)。同样,使用线程池和信号量来限制对资源的使用,但这些被限制的行为可能会导致资源死锁(Resource Deadlock)
3. 性能问题
1、线程的生命周期开销非常高
2、消耗过多的CPU资源
如果可运行的线程数量多于可用处理器的数量,那么有线程将会被闲置。
大量空闲的线程会占用许多内存,给垃圾回收器带来压力,而且大量的线程在竞争CPU资源时还将产生其他性能的开销。
3、降低稳定性
JVM在可创建线程的数量上存在一个限制,这个限制值将随着平台的不同而不同,并且承受着多个因素制约,包括JVM的启动参数、Thread构造函数中请求栈的大小,以及底层操作系统对线程的限制等。如果破坏了这些限制,那么可能抛出OutOfMemoryError异常。