线程与进程
考点:1、线程与进程的概念、通信方式
2、进程同步机制、死锁
3、多线程的实现方式、优缺点
1.概念
进程是一个程序在其自身的地址空间中的一次执行活动,是资源申请、调度和独立运行的单位。
线程是进程中的一个单一的连续控制流程,一个进程可以拥有多个线程。
线程调度的两种方式:抢占式(如:WinNT、UNIX、OS/2)、非抢占式(如DOS、Win3.X)。
进程和线程的区别在于,线程没有独立的存储空间,而是和所属进程中的其他线程共享一个存储空间。
2、线程的状态及其之间的通信
线程有4个状态:新建、就绪、运行、阻塞/等待/睡眠、死亡。各个状态之间的转化如图所示:
线程间的通信一般用 wait() 方法、notify() 方法和 notifyAll() 方法。它们都是Object类的最终方法,每个类都默认拥有。
wait() 方法可以使调用该方法的线程释放共享资源的锁,然后从运行状态中退出,进入等待队列,直到被再次唤醒。
notify() 方法可以唤醒等待队列中第一个等待同一共享资源的线程,并使该线程退出等待队列,进入可运行状态。
notifyAll() 方法可以使所有正在等待队列中等待同一共享资源的线程从等待状态退出,进入可运行状态,此时,优先级最高的那个线程最先执行。
3、进程间的通信
Windows 间用文件映射、内存共享、匿名管道、命名管道、邮件槽、剪贴板、动态数据交换、对象连接与嵌入、动态链接库、远程过程调用、NetBios 函数、Sockets 函数来进行进程之间的通信。
进程互斥是进程之间发生的一种间接性作用,一般是程序不希望的。通常的情况是两个或两个以上的进程需要同时访问某个共享变量。我们一般将发生能够访问共享变量的程序段称为临界区。两个进程不同同时进入临界区,否则就会导致数据的不一致,产生与时间有关的错误。解决互斥问题应该满足互斥和公平两个原则,即任意时刻只能允许一个进程处于同一共享变量的临界区,而且不能让任一进程无限期的等待。
进程同步是进程之间直接的相互作用,是合作进程间有意识的行为。
进程之间的同步互斥通过以下几个机制来实现:信号量、管程、会合、分布式系统。
4、死锁
线程之间由于抢占资源容易形成死锁。死锁是由于两个或多个线程都无法得到相应的锁而造成的所有线程都处于等待锁的状态的现象。
死锁有如下4个必要条件:
(1)互斥使用(资源独占)。
一个资源每次只能给一个进程使用。
(2)不可强占(不可剥夺)。
资源申请者不能强行从资源占有者手中夺取资源,资源只能由占有者自愿释放。
(3)请求和保持(部分分配,占有申请)。
一个进程在申请新的资源的同时保持对原有资源的占有(只有这样才能动态申请,动态分配)。
(4)循环等待。
假如存在如下一个进程等待队列:{P1,P2,...,Pn},
其中P1等待P2占有的资源,P2等待P3占有的资源......Pn等待P1占有的资源,形成一个进程等待环路。
死锁的处理策略如下:
(1)忽略该问题。
(2)检测死锁并且恢复。
(3)仔细地对资源进行动态分配,以避免死锁。
(4)通过破除死锁4个必要条件之一,来防止死锁产生。
5、多线程的实现方式
多线程有两种实现方法,分别是继承Thread类和实现Runnable接口。
利用继承Thread类创建的多个线程,虽然执行的是相同的代码,但彼此独立,且各自拥有自己的资源,互不干扰。而通过实现Runnable接口可以使多个线程拥有同一资源。所以一般在定义资源对象时实现Runnable接口。
实现Runnable接口相对于扩展Thread类来说,具有无可比拟的优势。这种方式不仅有利于程序的健壮性,使代码能够被多个线程共享,而且代码和数据资源相对独立,从而特别适合多个具有相同代码的线程去处理同一资源的情况。这样,线程、代码和数据资源三者有效分离,很好地体现了面向对象程序设计的思想。
6、多线程的优缺点
多线程的优点是提高并发程度、提高效率;缺点是数据同步困难、开发调试困难、任意使用多线程会降低效率(过犹不及)、不是可以随意使用多线程。