1. 安全性问题
2. 活跃性问题
3. 性能问题
安全性的含义是“永远不发生糟糕的事情”,而活跃性则关注于另一个目标,即“某件正确的事总会发生”。当某个操作无法继续执行下去的时候就会发生活跃性问题。例:如果线程A在等待线程B释放资源,而线程B永远不释放资源,那A就会永远等待下去。
活跃性问题包括:死锁、饥饿、活锁等。
活跃性意味着某件正确的事情最终会发生,但却不够好,因为我们通常希望正确的事情尽快发生。性能问题包括多个方面,例如服务时间过长,响应不灵敏,吞吐率过低,资源消耗过高,或者可伸缩性较低等。与安全性和活跃性一样,在多线程程序中不仅存在与单线程程序相同的性能问题,而且还存在由于使用线程而引入的其他性能问题。
在多线程程序中,当线程调度器临时挂起活跃线程并转而运行另一个线程时,就会频繁地出现上下文切换操作,这种操作将带来极大的开销:保存和恢复执行上下文,丢失局部性,并且CPU时间将更多地花在线程调度而不是线程运行上。当线程共享数据时,必须使用同步机制,而这些机制往往会抑制某些编译器优化,使内存缓存区中的数据无效,以及增加共享内存总线的同步流量。
死锁:A等待B的结果,B又等待A的结果就会产生死锁。产生死锁的情况有:
1. 锁顺序死锁
2. 动态锁顺序死锁
3. 协作对象之间互相调用需要获得锁的方法
4. 饥饿死锁
饥饿:由于线程无法访问它所需要的资源而不能继续执行时就产生了饥饿。比如,线程池中的任务需要无限期的等待一些必须由池中其他任务才能提供的资源或条件,除非线程池足够大,否则将发生线程饥饿,新任务没有线程去执行。
活锁:比如P1,P2两个人在路上相遇,互相谦让的避让对方,都改走其他路线,结果在另一条路上再次相遇,又互相避让,又相遇...导致双方都无法到达目的地,形成活锁。一个例子是网络上的载波监听,如果检测到冲突后,都相隔相同时间后再次检测冲突,就会形成活锁