线程并发一:概念理解

来源:互联网 发布:windows无法取得路径 编辑:程序博客网 时间:2024/05/22 10:14

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();    }}
原创粉丝点击