医用软件技术课件.ppt_第1页
医用软件技术课件.ppt_第2页
医用软件技术课件.ppt_第3页
医用软件技术课件.ppt_第4页
医用软件技术课件.ppt_第5页
已阅读5页,还剩65页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、医用软件技术,医疗器械与食品学院 郑建立 2012年4月,内容,多线程程序设计 Socket程序设计 状态机程序设计 Web Service程序设计 DICOM程序设计,多线程程序设计,进程基础,进程是可与其他程序并发执行的程序在一个数据集上的执行过程 进程的特征 动态性:最基本特征 进程是程序的执行过程 有生命周期 并发性:最重要的特征 多个进程实体在系统中同时存在 在一定的时间间内同时执行 独立性 独立运行、独立获得资源、独立调度的基本单位 异步性 进程按各自不可预知的速度推进 结构特征 程序段、数据段、进程控制块,进程与程序,进程的表示,进程实体 程序段:描述进程所要完成的功能 cs 数

2、据集:进程所需的数据和工作栈 ds es ss 进程控制块:进程的描述信息和控制信息,PCB,数据,程序,共享数据段,进程的基本调度状态,进程随着自身的推进和外界环境的变化而进行状态变迁,处在以下三种状态之一 执行状态(executing):获得必要的资源,占有处理机 就绪状态(ready):获得除处理机外的所有资源 阻塞状态(blocked):等待资源或某一事件 暂时状态 创建状态(created) 终止状态(terminated),进程状态间的转换,执行,就绪,阻塞,创建,终止,进程调度,抢占,I/O完成或 事件发生,I/O请求或 等待某事件,进程完成,进程执行的特点,间断性 异步方式执行

3、,走走停停 失去封闭型 资源共享,相互影响 不可再现性 初始条件和运行环境相同,结果却可能不同,示例,A:B: repeatrepeat n:=n+1; n:=n+1; until falseuntil false 每个n:=n+1可分解为: A1: R1:=nB1: R2:=n A2: R1:=(R1) +1B2:R2:=(R2)+1 A3: n:=(R1)B3:n:=(R1),示例,假如n=0, 若按顺序执行 A1,A2,A3,B1,B2,B3n=2 若并发执行,则同样的初值,会由于执行序列的不同,会出现不同的结果 A1,A2,A3,B1,B2,B3n=2 B1,B2,B3,A1,A2,A

4、3n=2 A1,A2,B1,A3,B2,B3n=1,进程间的同步与互斥,为保证进程并发执行的可再现性,要求并发进程间有相互制约关系 进程间相互制约关系有两类 同步:多个进程在执行速度上的制约 互斥:进程间竞争同一个排他性资源,而受到其他进程的制约,临界资源与临界区,临界资源 每次仅允许一个进程访问的资源 硬件如打印机、磁带机等 软件有消息缓冲队列、变量、数组、缓冲区等 临界区(Critical Section) 每个进程中访问临界资源的那段程序 进程进入临界区的原则 如果临界区空闲,一次仅允许一个进程进入。 如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。 进入临界区的进程

5、要在有限时间内退出,以便其它进程能及时进入自己的临界区。 如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。,信号量机制,早期同步方法: 软件方法:Dekker算法 十分繁琐 硬件方法:“test-and-set”指令、“交换”指令 1965年,荷兰人Dijkstra首先提出信号量(Semaphore)机制 信号量S P、V操作,记录型信号量S,结构: struct semaphore int value; struct pcb* L; 任何一个信号量必与某一资源相联系 Value: 记录对应资源的分配情况 初值:对应资源的数量 当前值: 0:无资源可分配 正值:该资源可

6、供分配的数量 负值:因等待该资源而被阻塞的进程数 L:链表指针,链接因等待该资源而被阻塞的进程,P、V操作,对信号量S,除初始化外,仅能通过两个标准的原子操作P(S)和V(S)来访问 P(S)操作:申请一份与S有关的资源 V(S)操作:释放一份与S有关的资源 P(S) V(S) S.value-; S.value+; if (S.value0) if (S.value=0) block(S.L);wakeup(S.L); 注意: P、V操作必须成对使用 P、V操作的原子性 操作系统内核提供的原语,用信号量实现互斥,所有互斥进程共用一个信号量mutex,又称互斥信号量,初值一般为1 每一进程的临

7、界区置于P(mutex)和V(mutex)之间,struct semaphor mutex; main() mutex.value=1; P1(); P2(); ,P1() do P(mutex); cs1; V(mutex); while(true); ,P2() do P(mutex); cs2; V(mutex); while(true); ,简单同步问题的实现,P1:repeat P2:repeat process next data; get data from buffer; add data to buffer; process last data; until false un

8、til false 只有当buffer中为满时,P2才能动作,否则必须等待 只有当buffer中为空时,P1才能动作,否则必须等待,P2,P1,Buffern,struct semaphor empty,full; main() empty.value=1; full.value=0; P1(); P2(); ,P1() do produce next data;,add data to buffer;,while(true); ,P(empty);,V(full);,P2() do,get data from buffer;,process last data; while(true); ,

9、P(full);,V(empty);,struct semaphor s; main() s.value=0; P1(); P2(); ,P1() do all work; V(s); P2() P(s); do all work; ,struct semaphor s; main() s.value=0; P1(); P2(); P3(); ,P1() do all work; V(s); P2() do all work; V(s); P3() P(s); P(s); do all work; ,经典进程同步问题,生产者-消费者问题 生产者与消费者互斥访问公用数据缓冲区 生产“数据”,消费

10、“数据” 读者-写者问题 数据文件或记录被多个进程共享并互斥访问的问题 允许多个Reader同时访问,但不允许一个Writer和其它Reader或任何两个以上的Writer同时访问 哲学家就餐问题 多资源共享及互斥访问 五个哲学家的思考与互斥共享五根筷子就餐的问题,生产者-消费者问题,生产者是制造或释放资源的进程 消费者是使用资源的进程 一组生产者和一组消费者通过一个循环缓冲队列联系起来 同步关系:需设置同步信号量 empty,full 仅当缓存区至少有一个空时,生产者才能向其中发送数据,否则生产者必须阻塞等待 仅当缓存区至少有一个满时,消费者才能从中提取数据,否则消费者必须阻塞等待 互斥关系

11、:需设置互斥信号量 mutex 多个生产者之间必须互斥地访问缓存区 多个消费者之间必须互斥地访问缓存区,生产者-消费者问题,信号量:mutex = 1 控制互斥访问缓冲区 empty = n, full = 0 空/满缓冲区个数 生产者消费者 生产出一个产品P(full); P(empty); P(mutex); P(mutex);从缓冲区取出一个产品 把新产品放入缓冲区V(mutex); V(mutex); V(empty); V(full);消费该产品 ,生产者-消费者问题,信号量:mutex = 1 控制互斥访问缓冲区 empty = n, full = 0 空/满缓冲区个数 生产者消费

12、者 生产出一个产品P(full); P(empty); P(mutex); P(mutex);从缓冲区取出一个产品 把新产品放入缓冲区V(mutex); V(mutex); V(empty); V(full);消费该产品 ,struct semaphor empty,full, mutex; struct message buffern, *pptr, *cptr; main() mutex.value=1; empty.value=n; full.value=0; producer(); consumer(); ,producer() do produce next product; P(e

13、mpty); P(mutex); send product to buffer(pptr); pptr+ mod n; V(mutex); V(full); while(true); ,consumer() do P(full); P(mutex); get product from buffer(cptr); cptr+ mod n; V(mutex); V(empty); consumer product; while(true); ,读者-写者问题,信号量: Wmutex = 1 控制互斥访问共享数据对象 Cmutex =1 控制读者互斥访问读者计数器 RC = 0 当前活动读者数 读者

14、写者 P(Cmutex); P(Wmutex); 若 RC = 0, 则P(Wmutex);对数据对象写 RC加1; V(Wmutex); V(Cmutex); 读数据对象 P(Cmutex); RC减1; 若 RC = 0, 则V(Wmutex); V(Cmutex); ,哲学家进餐问题,一个经典的同步问题,它是由Dijkstra1965提出并解决的。 哲学家以思考、吃饭交替进行的方式生活,他们共享一张周围有把椅子的圆桌,每人一把椅子,在桌子上摆有个饭碗和只筷子。 当一个哲学家思考时,他不与邻座同事发生联系。 当一哲学家饿了,他就试图拿起他左右两边的筷子吃饭。只有得到了两只筷子,他才可以吃饭

15、 当他用饭毕,就放下筷子并再次开始思考。 如果五位哲学家同时拿起左边的筷子,则因五位哲学家均在等待右边的筷子而使他们饥饿而“死”,线程基础,线程:线程是指程序中的一个执行流程。,进程:一个正在运行的程序。多任务操作系统可以同时运行多个进程。,单线程的程序只有一个执行的流程。,多线程的程序同时有多个执行的流程,可以同时完成多个任务,进程与线程的区别,“线程”是进程内部的一个执行流程,线程共享所在进程的内存和资源 。多线程的程序可以允许多个线程同时执行。,“进程” 是一个执行中的应用程序,包括它所用的内存和相关资源,每个进程都有自己独立的内存空间和系统资源,多任务的操作系统可以运行多个进程.,线程

16、与进程的比较,非常“节俭”的多任务操作方式 进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段 一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。 方便的通信机制 进程间数据的传递只能通过通信的方式进行,费时,不方便。 线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,快捷方便。,”同时“的含义,对于单CPU的主机 操作系统将CPU处理时间分成很多时间片,按照一定的调度机制将CPU时间轮流分配给各个任务。在任何

17、一个时刻,只有一个任务使用CPU,任务在运行。在一段时间内,每一个任务都获得了CPU的时间,由于切换时间很快,用户感觉不到任务的停顿,所以感觉多个任务同时运行。,对于多CPU主机 可以是真正意义上同时。,为什么要多线程,提高应用程序响应 ,改善用户体验。 充分发挥多核CPU的功能。 改善程序结构,Thread对象,using System.Threading; 构造函数 public Thread(ThreadStart start); public Thread(ParameterizedThreadStart start); 成员函数 启动线程:public void Start(); 暂

18、停线程:public static void Sleep(int millisecondsTimeout); 挂起线程:public void Suspend(); 恢复线程:public void Resume(); 中止线程:public void Abort(); 封锁线程:public void Join();,无参线程例:,ThreadStart ts=new ThreadStart(Calculate); Thread thread=new Thread(ts); thread.Start(); public void Calculate() double Diameter=0.5

19、; Console.Write(The Area Of Circle with a Diameter of 0 is 1Diameter, Diameter*Math.PI); ,委托 delegate: 相当于C+的函数指针 例:回调函数:,有参线程函数例:,ParameterizedThreadStart ts=new ParameterizedThreadStart(Calculate) Thread thread=new Thread(ts) ; thread.Start(0.9); public void Calculate(object arg) double Diameter=d

20、ouble(arg); Console.Write(The Area Of Circle with a Diameter of 0 is 1Diameter,Diameter*Math.PI); ,线程的中止,线程代码执行完毕 父线程退出 强行中止:Thread.Abort(),线程属性,Thread.ThreadState 属性的取值如下: Aborted:线程已停止; AbortRequested:Abort()方法已被调用,但是线程还未停止; Background:线程在后台执行; Running:线程正在正常运行; Stopped:线程已经被停止; StopRequested:线程正在

21、被要求停止; Suspended:线程已经被挂起,可调用Resume()方法重新运行; SuspendRequested:线程正在要求被挂起,但是未来得及响应; Unstarted:未调用Thread.Start()开始线程的运行; WaitSleepJoin:线程因为调用了Wait(),Sleep()或Join()等方法处于封锁状态;,创建线程函数 创建一个名为 Worker 的类,该类包含辅助线程将执行的方法 DoWork: public void DoWork() while (!_shouldStop) Console.WriteLine(worker thread: working.

22、); Console.WriteLine(worker thread: terminating gracefully.); 创建线程 Worker workerObject = new Worker(); Thread workerThread = new Thread(workerObject.DoWork); workerThread.Start(); 暂停线程 Thread.Sleep(1); 终止线程 线程函数运行结束,如本例中置_shouldStop=TRUE; 调用 Abort 来从一个线程终止另一个线程,但这会强行终止受影响的线程,而不管它是否已完成自己的任务,并且不提供清理资源

23、的机会,using System; using System.Threading; public class Worker / This method will be called when the thread is started. public void DoWork() while (!_shouldStop) Console.WriteLine(worker thread: working.); Console.WriteLine(worker thread: terminating gracefully.); public void RequestStop() _shouldSto

24、p = true; / Volatile is used as hint to the compiler that this data / member will be accessed by multiple threads. private volatile bool _shouldStop; ,public class WorkerThreadExample static void Main() / Create the thread object. This does not start the thread. Worker workerObject = new Worker(); T

25、hread workerThread = new Thread(workerObject.DoWork); / Start the worker thread. workerThread.Start(); Console.WriteLine(main thread: Starting worker thread.); / Loop until worker thread activates. while (!workerThread.IsAlive); / Put the main thread to sleep for 1 millisecond to / allow the worker

26、thread to do some work: Thread.Sleep(1); / Request that the worker thread stop itself: workerObject.RequestStop(); / Use the Join method to block the current thread / until the objects thread terminates. workerThread.Join(); Console.WriteLine(main thread: Worker thread has terminated.); ,main thread

27、: starting worker thread. worker thread: working. worker thread: working. worker thread: working. worker thread: working. worker thread: working. worker thread: working. worker thread: working. worker thread: working. worker thread: working. worker thread: working. worker thread: working. worker thr

28、ead: terminating gracefully. main thread: worker thread has terminated,线程安全,如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。 或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。,线程安全问题的引起: 全局变量 静态变量 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量

29、是线程安全的; 若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。,线程同步,Lock关键字 Monitor类 EventWaitHandler Mutex Interlocked类,lock关键字,将语句块标记为临界区,确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。 lock(lockobject) inti=5; Lockobject 应为 private 对象, 或 private static对象变量来保护所有实例所共有的数据,避免使用 public 类型。 lock的参

30、数必须是基于引用类型的对象,不是基本类型像bool,int;不能是字符串;,Monitor类,Monitor类通过向单个线程授予对象锁来控制对对象的访问。对象锁提供限制访问临界区的能力。 Enter():获得互斥锁,或被阻塞 Exit ():释放互斥锁 TryEnter():避免长期死等,超时后返回false lock关键字其实就是对Monitor类的Enter()和Exit()方法的封装 .,lock (x)DoSomething(); 等效于object obj = ( object )x;System.Threading.Monitor.Enter(obj);DoSomething();

31、System.Threading.Monitor.Exit(obj);,临界区,P操作,V操作,Monitor 用于同步: Pulse():向一个等待线程发送信号,通知锁定对象的状态已更改,并且锁的所有者准备释放该锁 PulseAll():向多个等待线程发送信号 Wait():释放对象上的锁,允许其他线程锁定和访问该对象 ,当前线程将被阻塞直到其他线程调用Pulse或PulseAll,生产者-消费者问题,信号量:mutex = 1 控制互斥访问缓冲区 empty = n, full = 0 空/满缓冲区个数 生产者消费者 生产出一个产品P(full); P(empty); P(mutex);

32、P(mutex);从缓冲区取出一个产品 把新产品放入缓冲区V(mutex); V(mutex); V(empty); V(full);消费该产品 ,classMonitorSampleprivateintn=1;/生产者和消费者共同处理的数据(临界资源)privateintmax=10000;privateObjectmonitor=newObject();publicvoidProduce()lock(monitor)for(;n=max;n+)Console.WriteLine(“生产者:第”+n.ToString()+“块蛋糕做好了”);/该方法使被阻塞线程进入了同步对象的就绪队列Mon

33、itor.Pulse(monitor);/调用Wait方法释放对象上的锁并阻塞该线程(线程状态为WaitSleepJoin)Monitor.Wait(monitor);,publicvoidConsumer()lock(monitor) while(true) /通知等待队列中的线程锁定对象状态的更改Monitor.Pulse(monitor);/释放对象上的锁并阻止当前线程,直到它重新获取该锁 /如果指定的超时间隔已过,则线程进入就绪队列Monitor.Wait(monitor,1000);Console.WriteLine(“消费者:吃第+n.ToString()+块蛋糕);,static

34、voidMain(stringargs)MonitorSampleobj=newMonitorSample();ThreadtProducer=newThread(newThreadStart(obj.Producer);ThreadtConsumer=newThread(newThreadStart(obj.Consumer);/Startthreads.tProducer.Start();tConsumer.Start();Console.ReadLine();,WaitHandle类及其子类,WaitHandle是Mutex,Semaphore,EventWaitHandler,Auto

35、ResetEvent,ManualResetEvent共同的祖先,它封装Win32同步句柄内核对象,也就是说是这些内核对象的托管版本。 WaitAll():等待所有指定的等待句柄都已收集到信号 WaitAny():等待任一指定的等待句柄收集到信号。,EventWaitHandler,Set():将事件状态设置为终止状态,允许一个或多个等待线程继续; Reset():将事件状态设置为非终止状态,导致线程阻塞 WaitOne():阻塞当前线程,直到当前线程的WaitHandle收到事件信号。 可以通过构造函数的参数值来决定其初始状态,若为true则事件为终止状态从而使线程为非阻塞状态,为false

36、则线程为阻塞状态。 如果某个线程调用WaitOne方法,则当事件状态为终止状态时,该线程会得到信号,继续向下执行。,ManualResetEvent和AutoResetEvent,都继承自EventWaitHandler,它们的唯一区别就在于父类EventWaitHandler的构造函数参数EventResetMode不同 AutoResetEvent.每次只允许一个线程进入,当某个调用WaitOne的线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待 ManualResetEvent不会自动将信号置为不发送,因而可以唤醒多个调

37、用WaitOne的线程,直到某个线程调用了ManualResetEvent.Set()方法。,例,张三、李四两个好朋友去餐馆吃饭,两个人点了一份宫保鸡丁,宫保鸡丁做好需要一段时间,张三、李四不愿傻等,都专心致志的玩起了手机游戏,心想宫保鸡丁做好了,服务员肯定会叫我们的。服务员上菜之后,张三李四开始享用美味的饭菜,饭菜吃光了,他们再叫服务员过来买单。 我们可以从这个场景中抽象出来三个线程,张三线程、李四线程和服务员线程,他们之间需要同步:服务员上菜张三、李四开始享用宫保鸡丁吃好后叫服务员过来买单。,publicclassEventWaitTestprivatestringname;/顾客姓名pr

38、ivatestaticManualResetEventeventWait=newManualResetEvent(false);privatestaticManualResetEventeventOver=newManualResetEvent(false);publicEventWaitTest(stringname)=name;publicstaticvoidProduct()Console.WriteLine(服务员:厨师在做菜呢,两位稍等 );Thread.Sleep(2000);Console.WriteLine(服务员:宫保鸡丁好了);eventWait.Set(

39、);while(true)if(eventOver.WaitOne(1000,false)Console.WriteLine(服务员:两位请买单);eventOver.Reset();,publicvoidConsume()while(true)if(eventWait.WaitOne(1000,false)Console.WriteLine(+:开始吃宫保鸡丁);Thread.Sleep(2000);Console.WriteLine(+:宫保鸡丁吃光了);eventWait.Reset();eventOver.Set();break;elseConsole.WriteLine(+:等着上菜无聊先玩会手机游戏);,publicclassApppublicstaticvoidMain(stringargs)EventWaitTestzhangsan=newEventWaitTest(张三);EventWaitTestlisi=newEventWaitTest

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论