死锁

死锁

线程在执行过程中等待锁释放,如果存在多个线程相互等待已经被加锁的资源,就会造成死锁。大多数语言的锁实现都支持重入的一个重要原因是一个函数体内加锁 的代码段中经常会调用其他函数,而其他函数内部同样加了相同的锁,在不支持重入的情况下,执行线程总是要获取自己尚未释放的锁。也就是说该条线程试图获取 一个自己已经获取而尚未释放的锁。死锁就此产生。还有最经典的哲学家就餐问题。

线程饥饿

互斥锁中提到获取不到锁的线程回去睡眠等待下一次竞争锁,如果下一次仍然得不到,就继续睡眠,这种持续得不到锁的情况我们称之为饥饿。一个很有意思的例子是关于小米手机饥饿营销的。将小米手机比作竞争资源,抢手机的用户就是线程,每次开抢都抢不到的用户就是线程饥饿。和饥饿相对的是公平,操作系统调度程序负责这种公平,使用分片或 nice 或执行比等方式避免得不到调度的线程活活饿死。Java 默认采用非公平的互斥锁,但是公平锁因为要防止饥饿需要根据线程调度策略做调整,所以性能会受到影响,而且一般情况下某条线程饿死的情况鲜有发生(因为调度本来就是不公平的),因此默认都是非公平的。