实验六 线程的创建与调度
线程的创建与撤销

实验报告规范
一、实验名称
线程的创建与撤销
二、实验目的
(1)熟悉windows系统提供的线程创建与撤销系统调用.
(2)掌握windows系统环境下线程的创建与撤销方法.
三、实验内容
(一)实验内容(实验指导书上的)
使用系统调用CreatThread()创建一个线程,并在线程中显示;Thread is Running!.为了能让用户清楚地看到线程的运行情况,使用Sleep()使线程挂起5s,之后使用ExitThread(0)撤销进程.
(二)主要代码(本节课学的函数在代码中是怎么实现的)
四、实验结果与总结
这部分内容简要概括自己实验的完成情况,实现了什么
成功在实验室电脑上运行老师在大屏幕上的程序并得到与老师相同的结果。
明白了Sleep(10000)等等函数的作用。
线程实例实验报告总结

一、实验目的本次实验旨在通过实例操作,深入了解线程的概念、创建、同步与通信机制,以及线程在实际编程中的应用。
通过实验,提高对线程的理解和运用能力,为以后开发多线程程序打下坚实基础。
二、实验环境1. 操作系统:Windows 102. 开发工具:Visual Studio 20193. 编程语言:C#三、实验内容1. 线程的基本概念线程是程序执行的最小单位,是操作系统进行资源分配和调度的基本单位。
线程具有以下特点:(1)线程是轻量级的,创建、销毁线程的开销较小。
(2)线程共享进程的资源,如内存、文件等。
(3)线程之间可以并发执行。
2. 线程的创建在C#中,可以使用以下方式创建线程:(1)使用Thread类```csharpThread thread = new Thread(new ThreadStart(MethodName));thread.Start();```(2)使用lambda表达式```csharpThread thread = new Thread(() => MethodName());thread.Start();```(3)使用匿名方法```csharpThread thread = new Thread(delegate () { MethodName(); });thread.Start();```3. 线程的同步线程同步是指多个线程在执行过程中,为了防止资源冲突而采取的协调机制。
C#提供了以下同步机制:(1)互斥锁(Mutex)```csharpMutex mutex = new Mutex();mutex.WaitOne();// 线程同步代码mutex.ReleaseMutex();```(2)信号量(Semaphore)```csharpSemaphore semaphore = new Semaphore(1, 1);semaphore.WaitOne();// 线程同步代码semaphore.Release();```(3)读写锁(ReaderWriterLock)```csharpReaderWriterLock rwlock = new ReaderWriterLock();rwlock.AcquireReaderLock();// 读取操作rwlock.ReleaseReaderLock();```4. 线程的通信线程通信是指线程之间传递消息、共享数据的过程。
线程调度实习报告

线程调度实习报告姓名李炜学号1100012810日期2014年3月6日目录内容一:总体概述 (3)内容二:任务完成情况 (3)任务完成列表(Y/N) (3)具体Exercise的完成情况 (3)内容三:遇到的困难以及解决方法 (7)内容四:收获及感想 (7)内容五:对课程的意见和建议 (7)内容六:参考文献 (8)内容一:总体概述这次的实习任务主要是通过对Nachos线程的调度机制来加深对线程调度的理解,因为Nachos本身是没有很复杂的调度机制的,所以这次实习中需要首先向Nachos添加带有优先级的线程调度算法,之后添加使用时间片调度,来使得线程的调度相对公平。
内容二:任务完成情况任务完成列表(Y/N)具体Exercise的完成情况第一部分Exercise1首先来看windows的线程调度,windows的调度单位就是线程,它采用的时基于动态优先级的、抢占式调度,结合时间配额调整,总是运行最高优先级线程。
就绪线程会按优先级进入相应队列,系统总是选择优先级最高的就绪线程让其运行,同一优先级的各线程按时间片轮转进行调度,多处理机系统中允许多个线程并行运行。
从这一点来看,有些像多级反馈队列调度的方法。
线程调度的触发事件有四种:一个线程进入就绪状态,如一个刚创建的新线程或一个刚刚结束等待状态的线程一个线程由于时间配额用完、从运行状态转入结束状态或等待状态一个线程由于调用系统服务而改变优先级或被Windows 系统本身改变其优先级一个正在运行的线程改变了它的亲合处理机集合Windows使用32个线程优先级,分成三类,实时优先级,可变优先级,系统线程(IDLE)。
一个线程用完了自己的时间配额时,如果没有其它相同优先级线程,Windows将重新给该线程分配一个新的时间配额,并继续运行。
当线程被抢占时,它被放回相应优先级的就绪队列的队首处于实时优先级的线程在被抢占时,时间配额被重置为一个完整的时间配额处于动态优先级的线程在被抢占时,时间配额不变,重新得到处理机后将运行直到剩余的时间配额用完如果刚用完时间配额的线程优先级降低了,Windows 将寻找一个优先级高于刚用完时间配额线程的新设置值的就绪线程如果刚用完时间配额的线程的优先级没有降低,并且有其他优先级相同的就绪线程,Windows 将选择相同优先级的就绪队列中的下一个线程进入运行状态,刚用完时间配额的线程被排到就绪队列的队尾(即分配一个新的时间配额并把线程状态从运行状态改为就绪状态)配额并继续运行下面来看linux的线程调度策略,linux将进程分为下面两类实时进程对调度延迟的要求最高,要求立即响应并执行调度策略:FIFO、Round Robin普通进程普通进程调度策略使用CFS,CFS是现在被内核采纳的调度器。
计算机操作系统实验-线程调度的优化与控制

计算机操作系统实验-线程调度的优化与控制西北工业大学操作系统实验实验报告一、实验目的掌握GeekOS系统的线程调度算法以及线程同步与互斥方法,实现线程调度的优化与控制。
二、实验要求1. 按照实验讲义P146页中的设计要求,增加线程调度算法的选择策略,使系统可以在时间片轮转调度和四级反馈队列调度之间切换,并且实现四级反馈队列调度算法,给出关键函数的代码以及实验结果。
2. 在GeekOS中实现信号量,使用信号量保证用户程序运行时的线程同步,给出关键函数的代码以及实验结果。
三、实验过程及结果答:1、进程间的调度实现:Get_Next_Runnable代码如下:struct Kernel_Thread* Get_Next_Runnable(void){struct Kernel_Thread* best = 0;int i, best_index_queue = -1;if (g_schedulingPolicy == ROUND_ROBIN) {struct Kernel_Thread* best_in_queue = NULL;for (i = 0; i < MAX_QUEUE_LEVEL; i++){best_in_queue = Find_Best(&s_runQueue[i]);if (best == NULL) {best = best_in_queue;best_index_queue = i;} else if (best_in_queue != NULL){if (best_in_queue->priority > best->priority) {best = best_in_queue;best_index_queue = i;}}}} else if (g_schedulingPolicy == MULTILEVEL_FEEDBACK) {if ( g_currentThread->priority != PRIORITY_IDLE ){if ( g_currentThread->blocked &&g_currentThread->currentReadyQueue > 0 )g_currentThread->currentReadyQueue--;}for (i = 0; i < MAX_QUEUE_LEVEL; i++){best = Find_Best(&s_runQueue[i]);best_index_queue = i;if (best != NULL)break;}if ( best->currentReadyQueue < MAX_QUEUE_LEVEL-1 )best->currentReadyQueue++;}KASSERT(best != NULL);Remove_Thread(&s_runQueue[best_index_q ueue], best);return best;}return EINV ALID;}bool atomic = Begin_Int_Atomic();if(g_Semaphores[sid].resources == 0){Wait(&g_Semaphores[sid].waitingThreads);KASSERT(g_Semaphores[sid].resources == 1);}KASSERT(0 < g_Semaphores[sid].resources); g_Semaphores[sid].resources--;End_Int_Atomic(atomic);return 0;}int V(sid){if(!validateSID(sid)){return EINV ALID;}bool atomic = Begin_Int_Atomic();g_Semaphores[sid].resources++;if(g_Semaphores[sid].resources == 1){Wake_Up_One(&g_Semaphores[sid].waiting Threads);}End_Int_Atomic(atomic);return 0;}修改后的Ping.c代码如下:#include <conio.h>#include <process.h>#include <sched.h>#include <sema.h>#include <string.h>int main(int argc , char ** argv){i nt i,j ; /* loop index */i nt scr_sem; /* id of screen semaphore */ i nt time; /* current and start time */i nt ping,pong; /* id of semaphores to syncprocesses b & c */t ime = Get_Time_Of_Day();s cr_sem = Create_Semaphore ("screen" , 1) ; /* register for screen use */p ing = Create_Semaphore ("ping" , 1) ;p ong = Create_Semaphore ("pong" , 0) ;f or (i=0; i < 5; i++) {P(pong);for (j=0; j < 35; j++);time = Get_Time_Of_Day() - time;P(src_sem);Print("Process Ping is done at time: %d\n",time);V(src_sem);V(ping);}t ime = Get_Time_Of_Day() - time;P (scr_sem) ;P rint ("Process Ping is done at time: %d\n", time) ;V(scr_sem);D estroy_Semaphore(pong);D estroy_Semaphore(ping);D estroy_Semaphore(scr_sem);r eturn (0);}修改后的Pong.c代码如下:#include <conio.h>#include <process.h>#include <sched.h>#include <sema.h>#include <string.h>int main(int argc , char ** argv){int i,j ; /* loop index */int scr_sem; /* id of screen semaphore */ int time; /* current and start time */int ping,pong; /* id of semaphores to sync processes b & c */time = Get_Time_Of_Day();scr_sem = Create_Semaphore ("screen" , 1) ; /* register for screen use */ping = Create_Semaphore ("ping" , 1) ;pong = Create_Semaphore ("pong" , 0) ;for (i=0; i < 5; i++) {P(ping);for (j=0; j < 35; j++);time = Get_Time_Of_Day() - time;P(src_sem);Print("Process Pong is done at time : %d\n",time);V(src_sem);V(pong);}time = Get_Time_Of_Day() - time;P (scr_sem) ;Print ("Process Pong is done at time: %d\n", time) ;V(scr_sem);return (0);}结果如图:四、实验分析1.调度:MLF调度算法的主要思想是系统有多个就绪队列,每个队列对应相应优先级,第一队列的优先级最高,然后优先级逐渐降低。
操作系统实验报告——调度算法

操作系统实验报告——调度算法1. 实验目的本实验旨在探究操作系统中常用的调度算法,通过编写代码模拟不同的调度算法,了解它们的特点和应用场景。
2. 实验环境本次实验使用的操作系统环境为Linux,并采用C语言进行编码。
3. 实验内容3.1 调度算法1:先来先服务(FCFS)FCFS调度算法是一种简单且常见的调度算法。
该算法按照进程到达的先后顺序进行调度。
在本实验中,我们使用C语言编写代码模拟FCFS算法的调度过程,并记录每个进程的等待时间、周转时间和响应时间。
3.2 调度算法2:最短作业优先(SJF)SJF调度算法是一种非抢占式的调度算法,根据进程的执行时间来选择下一个要执行的进程。
在本实验中,我们使用C语言编写代码模拟SJF算法的调度过程,并计算每个进程的等待时间、周转时间和响应时间。
3.3 调度算法3:轮转调度(Round Robin)Round Robin调度算法是一种经典的时间片轮转算法,每个进程在给定的时间片内依次执行一定数量的时间。
如果进程的执行时间超过时间片,进程将被暂时挂起,等待下一次轮转。
在本实验中,我们使用C语言编写代码模拟Round Robin算法的调度过程,并计算每个进程的等待时间、周转时间和响应时间。
4. 实验结果分析通过对不同调度算法的模拟实验结果进行分析,可以得出以下结论:- FCFS算法适用于任务到达的先后顺序不重要的场景,但对于执行时间较长的进程可能会导致下一个进程需要等待较久。
- SJF算法适用于任务的执行时间差异较大的场景,能够提高整体执行效率。
- Round Robin算法适用于时间片相对较小的情况,能够公平地为每个进程提供执行时间。
5. 实验总结本次实验通过模拟不同调度算法的实际执行过程,深入了解了各种调度算法的原理、特点和适用场景。
通过对实验结果的分析,我们可以更好地选择合适的调度算法来满足实际应用的需求。
在后续的学习中,我们将进一步探索更多操作系统相关的实验和算法。
线程池的任务调度流程

线程池的任务调度流程
线程池的任务调度流程一般如下:
1. 创建线程池:线程池对象创建时,会初始化一定数量的线程并启动。
2. 将任务提交到线程池:当有一个任务需要执行时,将其提交到线程池中。
3. 选择一个空闲线程去执行任务:线程池中的任务调度器会选择一个空闲的线程去执行任务。
如果没有空闲线程,则等待一个空闲线程。
4. 线程执行任务:选定的空闲线程会从任务队列中取出一个任务去执行。
5. 执行任务:线程会执行任务,直到任务执行完毕。
6. 任务执行完毕:任务执行完毕后,将会发送一个通知给任务调度器,告诉它当前线程可以再次使用。
7. 线程归还线程池:线程会将自己归还到线程池中,等待下一个任务的执行。
8. 重复执行:线程池中的任务调度器会一直重复执行上述步骤,直到线程池关闭。
总的来说,线程池的任务调度流程可以看作是一个生产者-消费者模型,任务提交者是生产者,线程池是消费者。
生产者提供任务,消费者负责执行任务,整个过程都是通过任务队列来协调的。
这种模型可以显著提高程序的并发和执行效率,减少线程的创建和销毁开销,提高系统的稳定性和可靠性。
创建线程的实验报告

一、实验目的1. 理解线程的概念和作用。
2. 掌握在Java中创建线程的方法。
3. 学习线程的生命周期和线程同步。
4. 熟悉线程的调度和同步机制。
二、实验环境1. 操作系统:Windows 102. 开发工具:IntelliJ IDEA3. 编程语言:Java三、实验内容1. 创建线程2. 线程生命周期3. 线程同步4. 线程调度四、实验步骤1. 创建线程(1)继承Thread类创建线程```javapublic class MyThread extends Thread { @Overridepublic void run() {// 线程要执行的任务System.out.println("子线程:" + Thread.currentThread().getName());}}```(2)实现Runnable接口创建线程```javapublic class MyRunnable implements Runnable {@Overridepublic void run() {// 线程要执行的任务System.out.println("子线程:" +Thread.currentThread().getName());}}```2. 线程生命周期线程生命周期包括以下五个状态:(1)新建(New):线程对象被创建后,处于此状态。
(2)就绪(Runnable):线程对象被创建后,调用start()方法,线程进入就绪状态。
(3)运行(Running):线程被调度到CPU上执行,处于运行状态。
(4)阻塞(Blocked):线程因为某些原因无法执行,进入阻塞状态。
(5)终止(Terminated):线程执行完毕或被强制终止,处于终止状态。
以下代码演示了线程的生命周期:```javapublic class LifeCycleDemo {public static void main(String[] args) {Thread thread = new Thread(new MyRunnable());System.out.println("线程状态:" + thread.getState());thread.start();System.out.println("线程状态:" + thread.getState());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程状态:" + thread.getState());}}```3. 线程同步线程同步是为了避免多个线程同时访问共享资源时出现冲突。
线程调度的三种方法

线程调度的三种方法
线程调度是操作系统中的重要概念之一,它指的是操作系统如何在多个线程之间分配处理器资源。
在实际的操作系统中,有三种常用的线程调度方法,分别是时间片轮转法、优先级调度法和多级反馈队列调度法。
时间片轮转法是一种基于时间片的调度方法。
操作系统将每个线程分配一个固定长度的时间片,当时间片用完后,操作系统会自动切换到下一个线程。
这种调度方法实现简单,能保证公平性,但是在高负载的情况下容易出现饥饿现象。
优先级调度法是一种基于线程优先级的调度方法。
每个线程都会被赋予一个优先级,优先级高的线程被优先调度。
这种调度方法可以保证高优先级线程的及时响应,但是如果优先级过于低的线程可能会被长期阻塞。
多级反馈队列调度法是一种综合了时间片轮转和优先级调度的
方法。
操作系统将线程按照优先级分成多个队列,并为每个队列分配不同的时间片。
当一个线程在一个队列中运行的时间超过了时间片,它就会被移到下一个队列中,直到运行完毕。
这种调度方法可以保证高优先级线程的及时响应,同时避免低优先级线程的饥饿现象。
总之,不同的线程调度方法适用于不同的场景,操作系统可以根据实际情况选择恰当的调度策略。
- 1 -。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验六线程的创建与调度
一、实验目的
1、线程是操作系统中最重要的概念之一。
现代操作系统为了增加程序的并发度,减少进程转换中系统的时空开销,几乎都引入了线程。
线程,也叫轻量级进程,引入线程后,仍以进程为单位分配系统资源,但处理机却是以线程为单位进行指派。
通过该实验,让学生体会线程的存在,了解线程与进程的关系,学习线程的创建与终止方法。
二、实验预习
1、什么是线程?为什么要建立线程?一个线程一般有几种不同的状态?
答:线程具有许多传统进程所具有的特征,所以又称为轻型进程或进程元,作为调度和分派的基本单位。
建立线程的目的是为了使多个程序能够并发执行,以提高资源利用率和系统吞吐量。
线程在运行时具有三种基本状态:执行状态,表示线程已获得处理机而正在运行;
就绪状态,表示线程已具备了各种执行条件,只须再获得CPU便可立即执行;
阻塞状态,表示线程在执行中因某事件受阻而处于暂停状态。
2、线程的实现方式有哪几种?操作系统是根据什么来感知线程的存在的?
答:线程的实现方式有用户级线程和内核支持线程以及实现了这两种类型的线程三种。
内核支持线程(KST):又称为内核级线程(KIT),在OS中的所有进程,无论是系统进程还是用户进程,都是在操作系统内核的支持下运行的,是和内核紧密相关的。
当前大多数OS 都支持内核支持线程。
用户级线程(ULT):用户级线程是和内核无关的,对于设置了用户级线程的系统,其调度仍是以进程为单位进行的。
用户级线程的主要缺点有系统调用的阻塞问题和进程中仅有一个线程能够执行。
组合方式:在组合方式线程系统中,内核支持多个内核支持线程的建立、调度和管理,同时,也允许用户应用程序建立、调度和管理用户级线程。
操作系统是根据线程控制块(TCB)来感知线程的存在的。
三、实验内容和要求
实验要求:写出实验过程和实验结果,给出实验结论。
实验内容:
1.通过SPY++工具来查看系统中的进程和线程;查看进程和线程的关系以及它们的优先级等信息。
2.在VC环境下建立一个控制台应用程序P1。
系统启动一个进程(因为支持线程,OS会在进程中主动创建一个主线程)来运行该程序。
输出该进程的ID号、以及该进程下面主线程的ID号。
程序代码如下:
#include<stdio.h>
#include<afxmt.h>
int main(){
printf("一个进程正在运行中\n");
printf("进程的主线程正在运行中\n");
printf("进程的ID号=%ld,线程ID号=%ld\n",
GetCurrentProcessId(),GetCurrentThreadId());
return 0;
}
3、在VC环境下建立一个控制台应用程序P1。
系统启动一个进程(因为支持线程,OS会在进程中主动创建一个主线程)来运行该程序。
在进程中,我们自己再创建一个子线程(子线程1),该子线程做的事情很简单,就是让它不停地输出如下信息:
子线程1正在运行第1次,其进程的ID号=~, 子线程1的ID号=~
子线程1正在运行第2次,其进程的ID号=~, 子线程1的ID号=~。
子线程1正在运行第20次,其进程的ID号=~, 子线程1的ID号=~
只要启动了一个子线程,实际上系统中是主线程和子线程1在并发执行。
主线程的功能是输出这样形式的内容:
主线程正在运行第1次,其进程的ID号=~,主线程的ID号=~
主线程正在运行第2次,其进程ID号=~, 主线程的ID号=~。
主线程正在运行第20次,其进程ID号=~, 主线程的ID号=~
多运行几次,观察主线程和子线程并发调动的次序。
每次调度都一样吗?为什么?进程ID、主线程ID和子线程ID每次都一样吗?
体会操作系统中并发的异步性。
程序代码如下:
#include<stdio.h>
#include<afxmt.h>
DWORD WINAPI Thread1(LPVOID lpparameter){
int i;
for(i=1;i<=20;i++){
printf("子线程1在运行中,它正在运行第%d times,所属进程的ID号=%ld, 本线程的ID号=%ld\n",i,GetCurrentProcessId(),GetCurrentThreadId());
}
return 0;
}
int main(){
int j;
printf("一个进程在运行中\n");
printf("主线程在运行中\n");
HANDLE hThread1=CreateThread(NULL,0,Thread1,NULL,0,NULL);
for(j=1;j<=20;j++){
printf("主线程正在运行第%d次;进程的ID号=%ld,线程ID号=%ld\n",
j,GetCurrentProcessId(),GetCurrentThreadId());
Sleep(500);
}
return 0;
}
多次运行的结果显示,每次调度是不一样的,因为操作系统中程序并发运行时的异步性原则,进程ID、主线程ID和子线程ID每次也都是不一样的。
4、在上面实验3的基础上,再创建一个子线程2,子线程2也如线程1一样输出,只是线程1改为线程2而已。
即,此时在计算机系统中形成主线程、线程1、线程2一起并发的阵势。
多运行几次,观察线程的调度情况,看看每次调度执行的结果一样不一样?
体会计算机系统中线程并发的异步性。
代码如下所示:
#include<stdio.h>
#include<afxmt.h>
DWORD WINAPI Thread1(LPVOID lpparameter){
int i;
for(i=1;i<=10;i++){
printf("子线程1在运行中,它正在运行第%d times,所属进程的ID号=%ld,本线程的ID号=%ld\n",i,GetCurrentProcessId(),GetCurrentThreadId());
}
return 0;
}
DWORD WINAPI Thread2(LPVOID lpparameter){
int i;
for(i=1;i<=10;i++){
printf("子线程2在运行中,它正在运行第%d times,所属进程的ID号=%ld,本线程的ID号=%ld\n",i,GetCurrentProcessId(),GetCurrentThreadId());
}
return 0;
}
int main(){
int j;
printf("一个进程在运行中\n");
printf("主线程在运行中\n");
HANDLE hThread1=CreateThread(NULL,0,Thread1,NULL,0,NULL);
HANDLE hThread2=CreateThread(NULL,0,Thread2,NULL,0,NULL);
for(j=1;j<=10;j++){
printf("主线程正在运行第%d次;进程的ID号=%ld,线程ID号=%ld\n", j,GetCurrentProcessId(),GetCurrentThreadId());
Sleep(500);
}
return 0;
}
多次运行的结果显示,每次调度执行是不一样的,因为计算机系统中线程运行时并发的异步性原则。
四、实验小结
通过本次实验的学习,体会线程的存在和引进线程的目的和意义,对线程有大致的了解,并进一步分析进程和线程之间的联系,从而更加具体的理解线程的概念,引入线程后,处理机是以线程为单位进行指派,但仍是以进程为单位分配系统资源的。
学习线程的创建和终止,在线程的创建函数执行完后,将返回一个线程标识符供以后使用,并对线程实现的三种方式进程了解其适应范围和优缺点,从而对线程有更加全面的理解和掌握。