并发编程中,如何区分临界区、阻塞、非阻塞、死锁、饥饿和活锁?