《learning hard C#学习笔记》读书笔记(19)多线程
19.1 多线程编程知识
19.1.1 进程与线程的概念
可以理解为一块包含某些资源的内存区域,操作系统通过进程方式把它工作划分为不同的单元。
一个应用程序可以对应多个进程。
线程是进程中的独立执行单元,操作系统调度线程来使应用程序工作。
一个进程中至少包含一个线程,称为主线程。
19.1.2 线程的调度
1、Time-critical:关键时间(最高的相对线程优先级)
2、Heightest:最高(翻译是这么翻译,但是并不是最高的相对线程优先级)
3、Above normal:高于标准
4、Normal:标准
5、Below normal:低于标准
6、Lowest:最低(翻译是这么翻译,但是并不是最低的相对线程优先级)
7、Idle:空闲
19.1.3 线程也分前后台
|
CLRT + F5 (不调试)效果图
通过分析,按 CLRT + F5 运行程序,你将会看到如图效果。如果按 F5 你将会看到输出结果一闪而过,因为主线程退出后,整个应用程序也跟着退出,就关闭了控制台程序。
1.所创建线程默认为非后台线程,所以注释掉 //backThread.IsBackground = true;(这时候不是后台线程了)
2.使主线程在后台线程执行完毕后再执行,即使主线程进入睡眠,且睡眠时间比后台线程长。
public Thread(ParameterizedThreadStart start, int maxStackSize);
19.2 线程的容器——线程池
19.2.1 线程池
线程池是一个存放线程的地方,这种集中存放有利于线程的管理。
CLR初始化时,线程池中没有线程。(线程池内部维护了一个操作请求队列).
执行异步操作时,需要调用 QueueUserWorkItem 方法将任务添加到线程池队列。线程池实现的代码会从队列中提取任务,并委派给线程池中的线程执行。
没有空闲的线程,线程池会创建一个新线程去执行提取的任务。
当线程池完成了某个任务,线程不会销毁,而是返回到线程池中,等待下一个请求。(由于不销毁,所以不会产生性能损失)
线程池创建的是后台线程,优先级是 Normal 。
19.2.2 通过线程池来实现多线程
使用线程池的线程,要调用静态方法 ThreadPool.QueueUserWorkItem ,以指定线程要调用的方法。该静态方法有两种:
public static bool QueueUserWorkItem(WaitCallback callBack);
public static bool QueueUserWorkItem(WaitCallback callBack, object state);
这两个方法用于向线程池队列添加一个工作项(work item)以及一个可选的状态数据。
工作项是指一个由 callback 参数标识的委托对象,被委托对象包装的回调方法由线程池来执行。
传入的回调方法匹配 System.Threading.WaitCallback 委托类型
|
19.2.3 协作式取消线程池线程
.NET Framework 提供了取消操作的模式,这个模式是协作式的。为了取消操作,我们必须创建一个 System.Threading.CancellationTokenSource 对象。
|
首先创建一个 CancellationTokenSource 实例,将该实例作为参数传入QueueUserWorkItem 方法。线程池会创建一个线程池线程,运行该方法传入的回调函数 callback ,并在 callback 中执行 Count 函数来计数。
在 Count 函数中检查 CancellationTokenSource 类实例的状态。当用户按回车键时,该实例的 IsCancellationRequested 属性将返回 ture 。因此退出 Count 方法。否则一直运行。
19.3 线程同步
多线程中,为了保证后者线程,只有等待前者线程完成之后才能继续执行。好比排队买票,前面的人没买票之前,后面的人必须等待。
19.3.1 多线程程序中存在的隐患
多线程可以提高程序的性能和用户体验。然而当我们创建多个线程后,它们可能同时访问某一个共享资源,这将损坏资源中所保存的数据。这时候我们需要使用线程同步,确保某一时刻只有一个线程在操作共享资源。
举例来说,火车票销售系统允许多人同时购买,因此该系统肯定采用了多线程技术。但由于系统中有多个线程在对同一资源(火车票)进行操作,我们必须确保只有其他线程执行结束后,新的线程才开始执行。这样可以避免多位顾客买到同一张票。
|
线程1从100张票开始出售,执行一段时间后,线程2开始执行,执行一段时间后,线程1又继续执行,两个线程交替,直至售完100张票。
19.3.2 使用监视器对象实现线程同步
监视器对象(Monitor)能够确保线程拥有对共享资源的互斥访问权,C# 通过 lock 关键字来提供简化语法。
|
使用 Monitor 锁定的对象需要引用类型,而不是值类型。
因为值类型变量传递给方法时,它将被装箱为一个单独的对象,之后传递给 Enter 方法;
而在将变量传递给 Exit 方法时,也会创建一个单独的引用对象。此时,传递给 Enter 方法的对象和传递给 Exit 方法的对象不同, Monitor 将会引发 SynchronizationLockException 异常。
使用 try.....finally 语句执行 Monitor ,如果不使用,程序会出现“死锁现象”;
19.3.3 线程同步技术存在的问题
它的使用比较繁琐。要用额外的代码把被多个线程同时访问的数据保卫起来,并获取和释放线程的同步锁。如果一个代码块忘记获取锁,就可能造成数据损坏。
使用线程同步会影响程序性能。因为获取和释放同步锁需要时间,并且决定哪个线程先获取锁,CPU也必须进行协调。
线程同步每次只允许一个线程访问资源,会导致线程阻塞。继而,系统会创建更多的线程,CPU也就负担更繁琐的调度工作。
|
调用 StartNew 函数对 Stopwatch 实例化,将运行时间设为0,开始测量时间。
《learning hard C#学习笔记》读书笔记(19)多线程的更多相关文章
- 《Hands-On Machine Learning with Scikit-Learn&TensorFlow》读书笔记
一 机器学习概览 机器学习的广义概念是:机器学习是让计算机具有学习的能力,无需进行明确编程. 机器学习的工程性概念是:计算机程序利用经验E学习任务T,性能是P,如果针对任务T的性能P随着经验E不断增长 ...
- 鸟哥Linux私房菜 基础学习篇读书笔记(10):Linux磁盘和文件系统管理(3)
本文总结了Linux操作系统来管理我们的硬盘和文件系统需要使用命令.当我们在系统中增加一个硬盘驱动器.什么是我们需要去通过这个硬盘就可以真正使用步骤?下面步骤: (1)对磁盘进行分区,新建能够使用的分 ...
- 鸟哥的Linux私房菜 基础学习篇读书笔记(9):Linux磁盘与文件系统管理(2)
上一篇文章主要从理论上分析了Linux的Ext2文件系统.这一篇主要解说怎样查看Linux的文件系统的容量以及解说Linux文件系统中的连接文件. 能够通过df和du命令来查看磁盘与文件夹的容量.df ...
- 人体和电脑的关系——鸟哥的LINUX私房菜基础学习篇读书笔记
CUP=脑袋: 每个人会做的事情都不一样(指令集的差异),但主要都是通过脑袋来判断与控制身体各部分的行动 内存=脑袋中存放正在思考的数据区块: 在实际活动过程中,我们的脑袋需要有外界刺激的数据(例如光 ...
- 人生效率手册:如何卓有成效地过好每一天--By张萌姐姐--读书笔记
读书笔记:<人生效率手册>:如何卓有成效地过好每一天--By张萌姐姐... 整本书看完的感受: 这本书主要讲的是生活中我们需要给自己一个目标,然后通过自己的努力去实现这个目标,书中说的很多 ...
- 强化学习读书笔记 - 06~07 - 时序差分学习(Temporal-Difference Learning)
强化学习读书笔记 - 06~07 - 时序差分学习(Temporal-Difference Learning) 学习笔记: Reinforcement Learning: An Introductio ...
- 【Deep Learning读书笔记】深度学习中的概率论
本文首发自公众号:RAIS,期待你的关注. 前言 本系列文章为 <Deep Learning> 读书笔记,可以参看原书一起阅读,效果更佳. 概率论 机器学习中,往往需要大量处理不确定量,或 ...
- Deep Learning(深度学习)学习笔记整理系列之(八)
Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...
- 强化学习读书笔记 - 02 - 多臂老O虎O机问题
# 强化学习读书笔记 - 02 - 多臂老O虎O机问题 学习笔记: [Reinforcement Learning: An Introduction, Richard S. Sutton and An ...
- 强化学习读书笔记 - 05 - 蒙特卡洛方法(Monte Carlo Methods)
强化学习读书笔记 - 05 - 蒙特卡洛方法(Monte Carlo Methods) 学习笔记: Reinforcement Learning: An Introduction, Richard S ...
随机推荐
- 【转】真正从零开始,TensorFlow详细安装入门图文教程!(帮你完成那个最难的从0到1)
AI这个概念好像突然就火起来了,年初大比分战胜李世石的AlphaGo成功的吸引了大量的关注,但其实看看你的手机上的语音助手,相机上的人脸识别,今日头条上帮你自动筛选出来的新闻,还有各大音乐软件的歌曲& ...
- SQL 归来
1. PL/SQL 转义 select order#, ……… from **** select col1 from A where col2 like '%\_keywors%' escape ' ...
- php-fpm优化方法详解
php-fpm优化方法 php-fpm存在两种方式,一种是直接开启指定数量的php-fpm进程,不再增加或者减少:另一种则是开始时开启一定数量的php-fpm进程,当请求量变大时,动态的增加php-f ...
- 关于tkCommand的各种事件的解释
superclass for callback/observer methods vtkCommand is an implementation of the observer/command des ...
- javascript数组array
注意:1.array的length不是只读的.可以从数组的末尾移出项或者向数组中添加新项.看下面例子: var colors = ["red","yellow" ...
- js构造函数的方法与原型prototype
把方法写在构造函数内的情况我们简称为函数内方法,把方法写在prototype属性上的情况我们简称为prototype上的方法 函数内的方法: 使用函数内的方法我们可以访问到函数内部的私有变量,如果我们 ...
- 虚函数的使用 以及虚函数与重载的关系, 空虚函数的作用,纯虚函数->抽象类,基类虚析构函数使释放对象更彻底
为了访问公有派生类的特定成员,可以通过讲基类指针显示转换为派生类指针. 也可以将基类的非静态成员函数定义为虚函数(在函数前加上virtual) #include<iostream> usi ...
- linux系统内核流转浅析
SJTUBEAR 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 我们通过简单 ...
- 常用shell 命令整理 一 进程 cpu
1.查看内存从大到小排列 ps -e -o "%C : %p : %z : %a"|sort -k5 -nr 分析: -e 显示进程 -o 按用户自定义格式显示 %C cpu %p ...
- eclipse常用快捷键
1. ctrl+shift+r:打开资源 这可能是所有快捷键组合中最省时间的了.这组快捷键可以让你打开你的工作区中任何一个文件,而你只需要按下文件名或mask名中的前几个字母,比如applic*.xm ...