同步(Synchronous)和异步(Asynchronous)
同步和异步通常用来形容一次方法调用。同步方法调用一旦开始,调用者必须等到方法返回后,才能继续后续的行为。异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作。而异步方法通常会在另外一个线程中“真实”地执行。
并发(Concurrency)和并行(Parallelism)
并发和并行都可以表示两个或者多个任务一起执行,但侧重点不同。并发偏重于多个任务交替地执行,而多个任务之间有可能还是串行的。而并行是真正意义上的同时执行。
并行的多个任务是真实的同时执行的,而对于并发来说,这个过程只是交替的,系统会在多个任务之间切换。实际上,如果系统内只有一个CPU时,运行多进程或多线程任务时,是不可能真实并行的,毕竟一个CPU一次只能执行一条指令。这种情况下,多进程或多线程是并发的,而不是并行的。真实的并行只可能出现在多CPU的系统中。
临界区
临界区用来表示一种公共资源或共享数据,可以被多个线程使用。但是,每一次只能有一个线程使用它,其他线程必须等待。在并行程序中,临界区资源是被保护的对象。
阻塞(Blocking)和非阻塞(Non-Blocking)
阻塞和非阻塞通常用来形容多线程之间的相互影响。比如一个线程占用了临界区资源,那么其他所有需要这个资源的线程就必须等待。等待会导致线程挂起,这种情况就是阻塞。
非阻塞强调没有一个线程可以妨碍其他线程执行,所有的线程都会尝试不断地向前执行。
死锁(Deadlock),饥饿(Starvation)和活锁(Livelock)
死锁,饥饿和活锁都属于多线程的活跃性问题。死锁是最糟糕的一种情况。
饥饿是指一个或多个线程因为种种原因无法获得所需要的资源,导致一直无法执行。比如它的线程优先级可能比较低,而高优先级的线程不断抢占它所需要的资源,导致低优先级的线程无法工作。另外一种可能是,某个线程一直占着关键资源不放,导致其他需要该资源的线程无法正常执行。
与死锁相比,饥饿还是有可能在未来的一段时间内解决的。
活锁是指两个线程都想要这个资源,但是它们都互相谦让,导致资源在两个线程之间不断地跳动,而没有一个线程可以同时拿到所有资源而正常执行。