在“多任务”一文中,我们提到了“协同式多任务”与“抢先式多任务”的概念和二者的区别,谈到现在主流的多任务实现是“抢先式多任务”,并且留下关于未来“协同式多任务”是否会被淘汰的疑问。今天在此再举几个例子作对比,为前面提出的疑问做个推测。

第一个例子先来看看“抢先式多任务”程序的运行表现。在这个例子中,我们用C#创建一个console程序,这个程序要做的事很简单,就是在命令行窗口记录下从程序启动到做完一个正整数累加(从1累加到50亿)的时间,程序代码如下:

 1 class WasteTime
 2     {
 3         public void run()
 4         {
 5             Int64 j;
 6
 7             for (Int64 i = 0; i < 5000000000; i++)
 8             {
 9                 j = i;
10             }
11         }
12 }

 1   class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Console.Write("Start  : ");
 6             Console.WriteLine(DateTime.Now.ToLongTimeString());
 7
 8             /*
 9             // Method 1
10             // Simple Loop
11
12             Int64 j;
13
14             for (Int64 i = 0; i < 5000000000; i++)
15             {
16                 j = i;
17             }
18             */
19
20
21             /*
22             // Method 2
23             // Using Object
24
25
26             WasteTime w1 = new WasteTime();
27             w1.run();
28
29             WasteTime w2 = new WasteTime();
30             w2.run();
31             */
32
33
34             /*// method 3
35             // multithreads
36             */
37             WasteTime w1 = new WasteTime();
38             WasteTime w2 = new WasteTime();
39
40             Thread t1 = new Thread(new ThreadStart(w1.run));
41             Thread t2 = new Thread(new ThreadStart(w2.run));
42
43             t1.Start();
44             t2.Start();
45
46             t1.Join();
47             t2.Join();
48
49
50             Console.Write("Finish : ");
51             Console.WriteLine(DateTime.Now.ToLongTimeString());
52
53
54             Console.ReadKey();
55         }
56     }

分别用三种不同的方法,得到如下的结果:

Method1

Method2

Method3

时间

13s

27s

16s

Cpu

使

                  注:以上数据在i5 3230m CPU电脑测试,测试过程中仅开启Visual Studio和资源监视器,图像右侧小部分曲线为开启截图软件导致

根据记录,可以看到如下现象:

1、 Method2和method3完成的工作量都是method1的两倍;

2、 method2大概用了method1两倍的时间做完累加运算;

3、 method3做完累加运算所需时间比method1多,但远比method2少;

4、 method1和method2在运算过程中都分别占用了一个cpu核心;

5、 method3在运算过程中占用了两个cpu核心;

分析以上现象,得到结论:在单线程的情况下,程序完成相同的运算所需时间基本相同,且在程序执行过程中始终占用同一个cpu内核,工作量和所需时间成线性比;在多线程的情况下,程序将任务分配在不同的cpu内核,工作量和所需时间不成线性比。

例子中,method2和method3其实可以看成是要分别完成两个任务(这里是两个相同的任务),在method2中,完成这两个任务是有先后顺序的,且在执行第二个任务的前提是第一个任务已经完成;在method3中,两个任务则是同时开始执行,且它们是独立完成的。method3的做法其实就是典型的“抢先式多任务”的实现,线程t1与t2由系统分配cpu资源和时间片,两个线程开始后,二者互相之间没有影响(仅限在这个例子中,因为线程是共享内存资源的),即不会因为其中一个线程执行的任务繁复而影响另一个线程的执行。但“抢先式多任务”的实现是需要付出更多的系统开销(overhead)的,所以,虽然两个任务分配到两个不同cpu内核,且并发执行,但它还是需要花费比method1更多的时间。这在前文也已经交代过,“抢先式多任务”的盛行,是以成熟的硬件支持为前提的。

我们针对method3,再进一步做一组测试,在这个测试中,我们分别创建1,2,3,4,5,6,7,8条线程,并记录下它们的执行时间和cpu使用情况,代码如下:

 1   class Program
 2   {
 3
 4         static void Main(string[] args)
 5      {
 6
 7             Console.Write("Start  : ");
 8        Console.WriteLine(DateTime.Now.ToLongTimeString());
 9
10             // method 3
11             // multithreads
12
13
14             WasteTime w1 = new WasteTime();
15             WasteTime w2 = new WasteTime();
16             //WasteTime w3 = new WasteTime();
17             //WasteTime w4 = new WasteTime();
18             //WasteTime w5 = new WasteTime();
19             //WasteTime w6 = new WasteTime();
20             //WasteTime w7 = new WasteTime();
21             //WasteTime w8 = new WasteTime();
22
23
24             Thread t1 = new Thread(new ThreadStart(w1.run));
25             Thread t2 = new Thread(new ThreadStart(w2.run));
26             //Thread t3 = new Thread(new ThreadStart(w3.run));
27             //Thread t4 = new Thread(new ThreadStart(w4.run));
28             //Thread t5 = new Thread(new ThreadStart(w5.run));
29             //Thread t6 = new Thread(new ThreadStart(w6.run));
30             //Thread t7 = new Thread(new ThreadStart(w7.run));
31             //Thread t8 = new Thread(new ThreadStart(w8.run));
32
33
34             t1.Start();
35             t2.Start();
36             //t3.Start();
37             //t4.Start();
38             //t5.Start();
39             //t6.Start();
40             //t7.Start();
41             //t8.Start();
42
43
44
45             t1.Join();
46             t2.Join();
47             //t3.Join();
48             //t4.Join();
49             //t5.Join();
50             //t6.Join();
51             //t7.Join();
52             //t8.Join();
53
54             Console.Write("Finish : ");
55             Console.WriteLine(DateTime.Now.ToLongTimeString());
56             Console.ReadKey();
57
58           }
59    }

测试结果记录如下:

线程数

1

2

3

时间

13s

16s

19s

Cpu使用率情况

线程数

4

5

6

时间

22s

28s

33s

Cpu使用率情况

 

线程数

7

8

时间

40s

46s

Cpu使用率情况

                注:以上数据在i5 3230m cpu上测试得到,测试过程中仅开启visual studio和资源监视器,图像右侧小部分曲线为开启截图软件导致

由以上数据可以看出:

1、 当线程数不超过cpu内核数时,每增加一条线程,完成任务付出的额外时间较之线程数超过cpu内核数时增加线程数完成任务所需时间更少;

2、 当线程数超过cpu内核数时,程序执行过程中,会有若干间隔时间cpu使用率骤降,且线程数越多,间隔越频繁;

由此可以进一步得出结论:在“抢先式多任务”实现中,尽管线程数超过了cpu内核数,但各线程还是被系统分配到了不同的内核执行;随着线程数量的增加,时间片的分配也变得更频繁,系统内销也随之加大,增加一条线程额外增加的时间也变得更多。

从中我们可以看出,“抢先式多任务”的原则,是要把诸多的任务进行分割,做平行处理,因此也带来了更大的系统开销。因为无论是时间片的分配、任务的挂起和恢复都是需要系统做更多的工作,并且这些工作都是建立在一定的硬件支持上的。

以上是“抢先式多任务”例子的分析,下面举个“协同式多任务”的例子,先看如下代码:

1     interface Runnable
2   {
4
5         void run();
6
7     }

 1     class Cat : Runnable
 2
 3     {
 4
 5         public void run()
 6
 7         {
 8
 9             Console.WriteLine("I am a cat");
10
11         }
12
13     }

 1     class Cow : Runnable
 2
 3     {
 4
 5         public void run()
 6
 7         {
 8
 9             Console.WriteLine("I am a cow");
10
11         }
12
13     }

 1     class Dog : Runnable
 2
 3     {
 4
 5
 6
 7         public void run()
 8
 9         {
10
11             Console.WriteLine("I am a dog");
12
13         }
14
15     }

 1     class WasteTime:Runnable
 2
 3     {
 4
 5         public void run()
 6
 7         {
 8
 9             int j;
10
11             for (int i = 0; i < 1000000000;i++ )
12
13             {
14
15                 j = i;
16
17             }
18
19             Console.WriteLine("==========This is an interval=============");
20
21         }
22
23     }    

 1     class Program
 2
 3     {
 4
 5         static void Main(string[] args)
 6
 7         {
 8
 9             List<Runnable> eventqueue = new List<Runnable>();
10
11
12
13             eventqueue.Add(new Cat());
14
15             eventqueue.Add(new Dog());
16
17             eventqueue.Add(new Cow());
18
19             eventqueue.Add(new WasteTime());
20
21
22
23             for (int i = 0; i < 10; i++)
24
25             {
26
27                 foreach (Runnable r in eventqueue)
28
29                 {
30
31
32
33                     r.run();
34
35                 }
36
37             }
38
39
40
41             Console.ReadKey();
42
43
44
45         }
46
47     }

例子中的代码要做的事,其实就是反复的每隔一段时间运行Cat,Cow,Dog三个类实例的run方法(WasteTime在这里仅仅为了取得时间间隔的效果),三个实例的run方法可以看成三个任务,因为相对于WasteTime间隔的时间,三个实例执行run方法十分迅速,可以看成是同一时间内进行,这就是一个典型的“协同式多任务”的实现——因为当执行Cat的run方法时,只要程序还没跳出该方法的函数体,cpu的使用权就一直掌握在该方法所属任务手中,这里的run方法就相当于主程序的回调函数;同样的道理适用在Cow和Dog中。任务的执行并非由系统做出统筹分配,而是“该到谁就到谁”。假如我们在其中某个run方法体内加入了复杂的代码,使得程序执行长时间不能跳出方法体,这时其他任务将被推迟执行。由于这种有秩序的执行多任务的方式,“协同式多任务”相对于“抢先式多任务”并不需要太大的系统内销,而且其在编码时能使程序员更清晰当前思路,因为这是一种程序“自上而下”的执行方式;但它却要求每个回调函数不能承载太繁重的任务。

由此可见,两种多任务的实现方式各有所长,在可预见的未来,都会在不同的应用场合中发挥作用。

转载于:https://www.cnblogs.com/sengnj/p/3566441.html

“抢先式多任务”“协同式多任务”相关推荐

  1. X86汇编语言从实模式到保护模式17:协同式任务切换

    目录 1. 多任务和任务切换概述 1.1 多任务系统 1.2 任务切换含义 1.2.1 切换任务上下文 1.2.2 上下文是什么 1.3 任务切换方式概述 1.3.1 协同式任务切换 1.3.2 抢占 ...

  2. RTOS 系统篇-多任务协同与复杂消息的设计

    RTOS 系统篇-多任务协同与复杂消息的设计 概述 对嵌入式系统的功能进行"任务划分",是 RTOS 中软件设计的关键.当任务划分比较合理时,整体的软件设计就会比较简洁.高效.容易 ...

  3. 线程的调度之协同式和抢占式

    大家好,我是神韵,是一个技术&生活博主.关于文章都是定位为基础,我不敢讲的太深入,因为我怕自己没时间.欢迎来点赞打卡,你们的行动将是我无限的动力. 今日主题是:线程的调度之协同式和抢占式 话不 ...

  4. CACC 协同式自适应巡航模型 搭建四辆车在carsim和simulink进行协同式自适应巡航 其中间距策略考虑领航车速的影响,各个车辆采用分层式控制,分层式控制器主要分为下层控制

    CACC 协同式自适应巡航模型(仿真软件版本:Carsim2016,Matlab2018b及以上) 搭建四辆车在carsim和simulink进行协同式自适应巡航,其中间距策略考虑领航车速的影响,各个 ...

  5. CACC 协同式自适应巡航模型 搭建四辆车在carsim和simulink进行协同式自适应巡航

    CACC 协同式自适应巡航模型(仿真软件版本:Carsim2016,Matlab2018b及以上) 搭建四辆车在carsim和simulink进行协同式自适应巡航,其中间距策略考虑领航车速的影响,各个 ...

  6. V2X应用场景之协同式自动驾驶

    转自:http://zhidx.com/p/96637.html V2X应用场景之协同式自动驾驶 这个应用场景我觉得是比较典型的,也想多花点时间给大家介绍一下,就是关于V2X在自动驾驶里面很典型的应用 ...

  7. 直播预告 | 斯坦福助理教授马腾宇:深度学习中的隐式和显式正则化

    人工智能作为科技领域最具代表性的技术,日益成为国际竞争的新焦点.当下,我国正逐步开展全民智能教育普及,设置人工智能相关课程,致力于建设人工智能的人才高地. 在此背景下,中关村海华信息技术前沿研究院立足 ...

  8. Algorithm Gossip (22) 中序式转后序式(前序式)

    前言 This Series aritcles are all based on the book <经典算法大全>; 对于该书的所有案例进行一个探究和拓展,并且用python和C++进行 ...

  9. BC之链式块状结构:区块链之链式块状结构——链式块状结构、内容相关配图

    BC之链式块状结构:区块链之链式块状结构--链式块状结构.内容相关配图 目录 区块链之链式块状结构.内容相关配图 1.区块链结构 区块链之链式块状结构.内容相关配图 1.区块链结构

最新文章

  1. 使用system语句出现不明确问题
  2. c语言子程序return,c语言return返回到哪
  3. linux学习笔记-不定时更新
  4. CRM Fiori launchpad请求响应结果的字段分析
  5. JS生成随机数并排序
  6. magisk核心功能模式是什么_科技板块——深入解析MM管理器
  7. 致敬学长!J20航模遥控器开源项目计划【开局篇】 | 先做一个开机界面 | MATLAB图像二值化 | Img2Lcd图片取模 | OLED显示图片
  8. 人脸识别接口_人脸识别双目摄像头模组应用系统
  9. java jmail_JavaMail学习--使用JMail发送邮件
  10. 删除烦人的微软拼音输入法
  11. 夜神模拟器连接手柄无反应_夜神安卓模拟器怎样连接手柄 夜神模拟器连接手柄图文教程...
  12. win7远程桌面连接
  13. Ruff 将助力广东金融高新区“区块链+”金融科技创新与应用落地
  14. 【Json转换为实体类】
  15. 第 三 十 八 天:Apache 选 项 和 模 块 问 题 附:php
  16. IOS 最新邓白氏编码申请
  17. jquery中的ajax方法请求后台数据
  18. 大学计算机excel函数课件,二级计算机考试Excel函数PPT课件
  19. 二、了解shiro架构 (10 Minute Tutorial on Apache Shiro)
  20. 《麦肯锡意识》前言 解决问题的战略模型-思维导图

热门文章

  1. JavaAndroid 基础知识梳理(8) 容器类
  2. elementUI v-loading不显示问题
  3. iOS 判断是否安装了微信、QQ客户端
  4. 如何在 IDEA 中创建并部署 JavaWeb 程序
  5. 图像修复:Object Removal by Exemplar-Based Inpainting 学习笔记
  6. [JAVA]从零开始的“桌面宠物”之路(一):动画效果
  7. FreeNOS-kernel目录下boot.S、链接脚本kernel.ld文件分析(四)
  8. Sklearn中predict_proba函数用法及原理详解
  9. 浅谈“戒色”与“慎独”
  10. 2022长安杯赛后复现