线程(Thread)
是一份独立运行的程序,有自己专用的运行栈。线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等。
当多个线程同时读写同一份共享资源的时候,可能会引起冲突。这时候,我们需要引入线程“同步”机制,即各位 线程之间要有个先来后到,不能一窝蜂挤上去抢作一团。线程同步的真实意思和字面意思恰好相反。线程同步的真实意思,其实是“排队”:几个线程之间要排队,一个一个对共享资源进行操作,而不是同时进行操作。
关于线程同步,
第一点:线程同步就是线程排队。同步就是排队。线程同步的目的就是避免线程“同步”执行。这可真是个无聊的绕口令。
第二点:“共享”这两个字。只有共享资源的读写访问才需要同步。如果不是共享资源,那么就根本没有同步的必要。
第三点:只有“变量”才需要同步访问。如果共享的资源是固定不变的,那么就相当于“常量”,线程同时读取常量也不需要同步。至少一个线程修改共享资源,这样的情况下, 线程之间就需要同步。
第四点是:多个线程访问共享资源的代码有可能是同一份代码,也有可能是不同的代码;无论是否执行同一份代码,只要这些线程的代码访问同一份可变的共享资源,这些线程之间就需要同步。
Reference:http://www.iteye.com/topic/164905
*********************************************************************************************************************************************************************
进程管理
概念:程序并不能单独运行,作为资源分配和独立运行的基本单位都是进程。
1、 程序并发执行的特征:
间断性,失去封闭性,不可再现性
2、 进程的三种基本状态
就绪状态,执行状态,阻塞状态
不少系统中只有上述三种状态,不少系统又引入了第三种状态 挂起状态
3、 引起挂起状态的原因
终端用户请求,父进程请求,负荷调节的需要,操作系统的需要
4、 进程状态的转换
在引入挂起状态后,又将增加从挂起状态(又称为静止状态)到非挂起状态(又称为活动状态)的转换;
活动就绪到静止就绪,静止就绪到活动就绪,活动阻塞到静止阻塞,静止阻塞到活动阻塞
进程控制块 PCB
5、 进程控制块PCB中的主要信息
1. 进程标识符
2. 处理机状态
3. 进程调度信息
4. 进程控制信息
6、 进程控制块PCB的组织方式
1. 链接方式
2. 索引方式
进程的控制
7、 引起创建进程的事件
用户登录,作业调度,提供服务,应用请求
8、 创建过程
申请空白PCB,为新进程分配资源,初始化进程控制块,将新进程插入就绪队列
9、 进程同步的概念:进程同步的主要任务是使并发执行的诸进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性。
10、 同步机制应遵循的规则
空闲让进,忙则等待,有限等待,让权等待。
11、 管程机制
一个管程定义了一个数据结构和能为并发进程所执行的一组操作,这组操作能同步进程和改变管程中的数据
12、 进程通信:
高级进程通信可归结为三大类:共享存储器系统,消息传递系统,管道通信系统。
13、 线程
进程是一个可拥有资源的独立单位,线程是一个调度和分派的基本单位。
14、 线程的属性:
轻型实体,独立调度和分派的基本单位,可并发执行,共享进程资源。
15、 多线程的操作系统中进程属性:
作为系统资源的分配单位,可包括多个线程,进程不是一个可执行的实体。
16、 在多线程的OS中通常提供多种同步机制,互斥锁,条件变量,技术信号量以及多读,单写锁。
*****************************************************************************************************************************************************
a.进程是资源分配的基本单位,线程是cpu调度,或者说是程序执行的最小单位。在Mac、Windows NT等采用微内核结构的操作系统中,进程的功能发生了变化:它只是资源分配的单位,而不再是调度运行的单位。在微内核系统中,真正调度运行的基本单位是线程。因此,实现并发功能的单位是线程。
b.进程有独立的地址空间,比如在linux下面启动一个新的进程,系统必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种非常昂贵的多任务工作方式。而运行一个进程中的线程,它们之间共享大部分数据,使用相同的地址空间,因此启动一个线程,切换一个线程远比进程操作要快,花费也要小得多。当然,线程是拥有自己的局部变量和堆栈(注意不是堆)的,比如在windows中用_beginthreadex创建一个新进程就会在调用CreateThread的同时申请一个专属于线程的数据块(_tiddata)。
c.线程之间的通信比较方便。统一进程下的线程共享数据(比如全局变量,静态变量),通过这些数据来通信不仅快捷而且方便,当然如何处理好这些访问的同步与互斥正是编写多线程程序的难点。而进程之间的通信只能通过进程通信的方式进行。
d.由b,可以轻易地得到结论:多进程比多线程程序要健壮。一个线程死掉整个进程就死掉了,但是在保护模式下,一个进程死掉对另一个进程没有直接影响。
e.线程的执行与进程是有区别的。每个独立的线程有有自己的一个程序入口,顺序执行序列和程序的出口,但是线程不能独立执行,必须依附与程序之中,由应用程序提供多个线程的并发控制。
2)什么是线程安全如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。
如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。 线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
3)多线程同步与互斥有几种实现方法?都是什么?(C++)
临界区(CS:critical section)、事件(Event)、互斥量(Mutex)、信号量(semaphores),需要注意的是,临界区是效率最高的,因为基本不需要其他的开销,二内核对象涉及到用户态和内核态的切换,开销较大,另外,关键段、互斥量具有线程所有权的概念,因此只可以用于线程之间互斥,而不能用到同步中。只有互斥量能完美解决进程意外终止所造成的“遗弃问题”。
4)多线程同步和互斥有何异同,在什么情况下分别使用他们?举例说明
所谓同步,表示有先有后,比较正式的解释是“线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。
所谓互斥,比较正式的说明是“线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。线程互斥可以看成是一种特殊的线程同步。”表示不能同时访问,也是个顺序问题,所以互斥是一种特殊的同步操作。
举个例子,设有一个全局变量global,为了保证线程安全,我们规定只有当主线程修改了global之后下一个子线程才能访问global,这就需要同步主线程与子线程,可用关键段实现。当一个子线程访问global的时候另一个线程不能访问global,那么就需要互斥。
例:
>>>以下多线程对int型变量x的操作,哪几个需要进行同步: A. x=y; B. x++; C. ++x; D. x=1;
答案是ABC,显然,y的写入与x读y要同步,x++和++x都要知道x之前的值,所以也要同步。
>>>多线程中栈与堆是公有的还是私有的
A:栈公有, 堆私有
B:栈公有,堆公有
C:栈私有, 堆公有
D:栈私有,堆私有
答案是C,栈一般存放局部变量,而程序员一般自己申请和释放堆中的数据。
>>>在Windows编程中互斥量与临界区比较类似,请分析一下二者的主要区别。
临界区、互斥量、信号灯、事件的区别总结
针对这个题目的话,答案主要有以下几点:
1)互斥量是内核对象,所以它比临界区更加耗费资源,但是它可以命名,因此可以被其它进程访问
2)从目的是来说,临界区是通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。 互斥量是为协调共同对一个共享资源的单独访问而设计的。
>>>一个全局变量tally,两个线程并发执行(代码段都是ThreadProc),问两个线程都结束后,tally取值范围。