这篇文章是关于多线程的一些基础知识的学习总结,以备学习和参考,如有错误及不当之处还希望大家批评指正、相互学习。
基本概念
- 同步和异步
同步:操作一旦开始,调用者必须等到方法调用返回后,操作才能继续进行。
异步:操作开始后,不必等到方法返回,即可开始其他操作。 - 并行和并发
并行:假设有两个cpu同时执行不同的线程,叫并行。
并发:有一个cpu,一会儿执行这个线程,一会儿执行那个线程,叫并发。 - 临界区
是值公共的资源可以被共同访问的那部分资源。 - 阻塞和非阻塞
阻塞:在一个线程对临界区进行操作时,其他线程暂时挂起,叫阻塞。
非阻塞:允许多个线程同时访问临界区,叫非阻塞。 - 死锁
指多个线程占用一部分资源并请求另一部分资源,在改变现在状况之前程序不能继续进行,进而程序处于永久等待状态。
死锁产生的条件:
a. 互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
b. 请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
c. 非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
d. 循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。
关于死锁我有一个有趣的理解,死锁就像一对情侣在吵架,每个人都有自己的理而征求对方放弃所占有的理,在这种情况改变之前感情不能继续进行。 - 活锁
程序请求的资源一直未被满足,不是向死锁那样是静态的,活锁是动态的。例如两个进程T1和T2分别占有A,B两个资源,只有同时占有A,B两个资源时程序才能继续,在T1和T2分别释放A,B资源后T1占用B,T2占用A,如此往复进而程序不能继续运行。
正如两个人走路碰头,A,B发现碰头,A往左,B也往左,A往右,B也往右,如此往复进而A和B都不能继续走路。 - 饥饿
饥饿是指线程由于优先级别较低,进而导致调度不到该线程,发生饥饿现象。 - 线程和进程
线程:线程可以利用进程所拥有的资源,在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位。
进程:进程是一段程序的启动、运行和结束,进程包含多个线程。 线程的基本操作
新建(new Thread)
当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
例如:Thread t=new Thread();就绪(runnable)
线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t.start();运行(running)
线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。死亡(dead)
当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。自然终止:正常运行run()方法后终止
异常终止:调用stop()方法让一个线程终止运行
堵塞(blocked)
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。
正在等待:调用wait()方法。(调用motify()方法回到就绪状态)
被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)