死锁和活锁

一、多线程的资源竞争

多线程编写的复杂度其实就是体现在资源的竞争控制上,这个在以前的文章中反复提到过。资源竞争主要是两种情况,数据竞争和执行任务竞争。通过前面的文章介绍可以知道,锁可以解决这些问题,但如何更好的处理竞争问题并达到最优,这就需要策略和算法了。包括提到的无锁编程,其实也是一种解决的策略。
无论是在单核亦是多核的情况下,资源的竞争总是不可避免的,所以对资源的控制就是需要认真对待的一个问题。

二、死锁

所谓死锁,其实就是“集合中的每一个进程都在等待只能由本集合中的其他进程才能引发的事件,那么该组进程是死锁的。”死锁,即意味着程序已经无法继续工作,大量的计算机资源被浪费。死锁形成需要以下条件:
1、互相持有
就是A进程持有B进程需要继续工作的资源,反过来,B进程同时也持有A进程需要继续工作的资源。
2、循环等待
这个好理解,就是两个进程间互相需要对方的资源,而且不断等待着对方资源。
3、不可剥夺
和优先级一样,不能够一个进程强行从另外一进程把需要的资源强制夺取过来
4、资源互斥
这个意思是说资源必须是独的,一个进程拥有,另外一个进程就不能拥有。

三、活锁

活锁(liveLock),指线程间资源冲突激烈,引起线程不断的尝试获取资源,不断的失败。活锁有点类似于线程饥饿,虽然资源并没有被别人持有,但由于各种原因而无法得到。最常见的原因是进程组的执行顺序不合理,导致某些先需要的资源被后置。活锁和死锁的不同在于,活锁的状态是变化的,只是无法达到目的。活锁有可能在一定时间后自动解开,但死锁不能。
一般来说,解决活锁的方式是采用退避的方式,也就是说让进程对资源的需求产生随机性,就有极大的可能解决活锁。

四、竞争异常激烈

护航现象(Lock Convoys),就是一个组进程中,等待同一个锁,如果持有这个锁的某个线程时间片轮转完成后,其它线程都需要这个持有锁的进程唤醒释放才能开始工作。而如果锁的实现是以公平的方式实现的,意味着所有的进程工作都必须按顺序进行,从而导致所有的进程都必须阻塞。
在实际应用中,经常会遇到生产者消费者的问题,如果二者的速度严重不匹配,就会产生对锁竞争的激烈现象。也就是说在线程或进程的执行过程中,如果对锁操作的时间小于执行的时间就会产生激烈的锁获取动作,这时就可能产生护航现象。解决这种现象的一般方法是对资源进行拆分,把锁一个资源改成多个锁去锁多个资源,也就是说控制锁的粒度。

五、总结

锁的问题最好还是能够使用无锁编程来实现,这是对锁的一个最完美的解决,锁都没有了,它的各种不良的后果,自然就烟消云散了。

你可能感兴趣的:(C++,架构设计,c++)