1.同步(Synchronous) 和异步(Asynchronous)
同步和异步通常来形容一次方法的调用,同步方法调用一旦开始,调用者必须等到方法调用结束才成继续后续的行为。异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回调用者可以继续后续的操作。如果异步调用需要返回结果,那么当这个异步调用真实完成时,则会通知调用者。
2.临界区
临界区一般用来表示多线程的共享资源数据。也就是并发情况下要保护的对象。
3.阻塞(Blocking)和非阻塞(Non-Blocking)
阻塞和非阻塞一般用来多线程之间的相互影响或对IO的操作。当一个线程占用了临界区的资源,其他线程线程在调用临界区资源的时候必须等待,等待会导致线程挂起,这种情况就是阻塞。如果当前线程不释放临界区资源,那么其他所用线程都将不能工作
非阻塞:强调没用一个线程可以妨碍其他线程执行,所用线程都会不断尝试获取临界区资源,获取不到直接返回,下次再获取。
4. 死锁(Deadlock)、饥饿(Starvation)、活锁(Livelock)
几种状态都属于多线程活跃性的问题,当出现这种问题的时候,也就表明相关线程出现了问题,很难再执行下去
死锁:是最糟糕的一个问题,是指两个或两个以上的进程(线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外部处理作用,它们都将无限等待下去。
死锁形成条件:
互斥条件:所谓互斥就是进程在某一时间内独占资源。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
死锁形成的常见情况有以下几种:
a.忘记释放锁
b.单线程重复申请锁
void sub_func()
{
EnterCriticalSection();
do_something();
LeaveCriticalSection();
}
void data_process()
{
EnterCriticalSection();
sub_func();
LeaveCriticalSection();
}
c.多线程多锁申请
void data_process1()
{
EnterCriticalSection(&cs1); // 申请锁的顺序有依赖
EnterCriticalSection(&cs2);
do_something1();
LeaveCriticalSection(&cs2);
LeaveCriticalSection(&cs1);
}
void data_process2()
{
EnterCriticalSection(&cs2); // 申请锁的顺序有依赖
EnterCriticalSection(&cs1);
do_something2();
LeaveCriticalSection(&cs1);
LeaveCriticalSection(&cs2);
}
d.环形锁申请
/* 多个线程申请锁的顺序形成相互依赖的环形:
* A - B
* | |
* C - D
*/
饥饿:是指线程因种种原因无法获取所需要的资源导致一直无法执行。
一般会出现饥饿状态有两种原因:
a.某一线程一直占用资源
b.线程优先级问题
活锁:是指线程1可以使用资源,但它很礼貌,让其他线程先使用资源,线程2也可以使用资源,但它很绅士,也让其他线程先使用资源。这样你让我,我让你,那么就会出现资源不断在两个线程中跳动,而没有一个线程可以同时拿到所用资源而正常执行
5.线程优先级
Java中线程可以有自己的优先级,优先级高的线程在竞争资源时会更有优势,但如果无法精准控制多线程的优先级,会导致低优先级的线程可能一直抢占不到资源,从而始终无法运行。所以设置线程优先级要谨慎。在Java中,使用1 到10 表示线程优先级。一般可以使用Thread 类中内置的三个静态标量表示:
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
执行下面的示例,可以看到高优先级的线程在大部分情况下都会先执行完任务。
public class PriorityDemo {
public static class HightThread extends Thread {
static int count = 0;
public void run(){
while (true){
synchronized (PriorityDemo.class){
count ++;
if(count > 1000000){
System.out.println("HightThread is complete!");
break;
}
}
}
}
}
public static class LowThread extends Thread {
static int count = 0;
public void run(){
while (true){
synchronized (PriorityDemo.class){
count ++;
if(count > 1000000){
System.out.println("LowThread is complete!");
break;
}
}
}
}
}
public static void main(String[] args){
Thread high = new HightThread();
Thread low = new LowThread();
high.setPriority(Thread.MAX_PRIORITY);
low.setPriority(Thread.MIN_PRIORITY);
low.start();
high.start();
}
}