.NET同步与异步之相关背景知识(六)

在之前的五篇随笔中,已经介绍了.NET 类库中实现并行的常见方式及其基本用法,当然、这些基本用法远远不能覆盖所有,也只能作为一个引子出现在这里。以下是前五篇随笔的目录:

.NET 同步与异步之封装成Task(五)

.NET 实现并行的几种方式(四)

.NET 实现并行的几种方式(三)

.NET 实现并行的几种方式(二)

.NET 实现并行的几种方式(一)

话再说回来,这五篇随笔都属于《同步与异步》系列。同步与异步、这是一个很大、很笼统的话题,以笔者所学很难将其将其介绍清楚,不过、笔者还是会尽力的。以下是笔者打算在近期介绍的一些知识点(大纲)、当然如果您有更好的意见或建议、欢迎评论留言。

1、与“同步与异步”相关的一些背景知识(即当前随笔)

  线程上下文、上下文切换、竞争条件(竞态条件)、锁、死锁。

2、锁(Lock、Monitor、ReaderWriterLockSlim)(预计1-2篇随笔)

3、轻量级的锁(Interlocked、SpinLock)(预计1篇随笔)

https://msdn.microsoft.com/zh-cn/library/system.threading.spinlock(v=vs.110).aspx

https://msdn.microsoft.com/zh-cn/library/system.threading.interlocked(v=vs.110).aspx

4、WaitHandle家族 (预计2篇随笔)

https://msdn.microsoft.com/zh-cn/library/system.threading.waithandle(VS.80).aspx

https://msdn.microsoft.com/zh-cn/library/system.threading.semaphoreslim(v=vs.110).aspx

5、警惕闭包中的变量捕获(预计1篇随笔)

6、线程安全的集合(预计1篇随笔)

7、因地制宜——CPU密集型操作和IO密集型操作(预计2篇随笔、各写一篇)




好了,大纲暂时就先这些了,下面进入该篇随笔的正文、线程方面的相关背景知识:

线程上下文

线程的强大之处、我就不再强调了。如此强大的线程、想要“免费”使用它,似乎是不可能的,就像有句话说的那样:出来混总是要还的。

Windows中每开辟一个线程、系统都要默认分配一定量的内存空间、其中有一块内存空间用来保存CPU寄存器中的值,我们把这个内存块称为线程上下文。

内存空间中除了寄存器集合之外,还有一部分叫线程栈,线程栈的内存开销要比寄存器集合的内存开销大的多。

上下文切换

线程、是程序执行流的最小单元,它就像一个逻辑CPU(或者虚拟CPU)。在系统中多个逻辑CPU(线程)共享计算机中的物理CPU核心(一个CPU可能有多个核心)。

Windows在任何时刻,都只会把一个线程分配给一个CPU核心去运行。被分配的线程运行一个“时间片”长度后,时间片到期,此时Windows会切换上下文。

每次切换上下文,Windows都会做如下操作:

1、将CPU寄存器中的值保存到当前的线程上下文中。2、从现有的线程集合中挑选一个线程。3、将挑选的线程的上下文加载到CPU寄存器中。

上下文切换完成后,CPU会运行所选线程,直到它的时间片到期,然后再次发生上下文切换。Windows大约会30毫秒切换一次线程上下文。

事实上、上下文切换对性能的影响可能超乎了你的想象:

线程在运行时,线程所需的代码和数据都存放在CPU的高速缓存中,这使得CPU不必经常访问内存RAM(访问它的速度要比访问高速缓存的速度慢的多)。

当Windows进行上下文切换后、线程运行所需的代码和数据,可能不在CPU的高速缓存中,因此CPU必须访问RAM来填充高速缓存、以恢复CPU的高速运行。

但是,大约30毫秒后,上下文切换再一次发生了。

另外、当一个时间片结束后,如果Widnows决定继续运行同一个线程,那么将不发生上下文切换。

线程也可以自主终止其时间片,节省出来的时间、CPU可以用来运行其他线程。

关于 Thread.Sleep  方法、这里说一下它的三个特殊参数, -1, 0, 1 毫秒。

-1,当前线程将永远休眠(此参数其实没有意义,虽然Windows不再调度该线程,但它还是占用着内存)。

0,当前线程放弃了剩余的时间片,促使Windows发生上下文切换。当然此时Windows有可能还会继续运行当前休眠的线程(没有相同和更高优先级的线程需要运行的时候)

1,Sleep(0), 是不允许线程优先级较低的线程运行的, 而 Sleep(1) 会强制发生一次上下文切换。

竞争条件

假如有以下一行代码、假定当时 整形变量i的值为 0 :

i = i + 1;

当有两个线程同时运行该行代码后,变量i的值变为了1。这时候的结果和预期的值2不一致,这时候我们认为是由于竞争条件引发了安全问题。

引发该问题的原因是:多个线程同时访问了共享资源。

存在竞争条件的代码,我们认为是线程不安全的代码。

锁 和 死锁

解决竞争条件的典型方案是,获取共享资源的独占式访问特权,而获取该特权的过程、我们称之为加锁。而这个特权、就是锁。

但是、加锁和释放锁的过程中开销较大、性能影响较大。还有一类更好的解决方案:原子操作,我有时候也会把它称为轻量级锁。

当两把锁相互等待对方释放的时候、我们认为此时发生了死锁。

随笔暂告一段落、下一篇随笔介绍: 锁(Lock、Monitor、ReaderWriterLockSlim)(预计1-2篇随笔)

附,Demo : http://files.cnblogs.com/files/08shiyan/ParallelDemo.zip

参见更多:随笔导读:同步与异步

(未完待续...)

时间: 2024-08-23 11:14:45

.NET同步与异步之相关背景知识(六)的相关文章

WEB相关背景知识(新手)

1.评估域名类型 .com--商业实体 .edu--仅限有学位或更高等学历授予资格的高等教育使用 .gov--仅限政府使用 .net--与Internrt网络支持相关的团体,通常是Internet服务提供商或者电信公司 .org--非盈利组织 2.HTML -HTML是一套标记符号或者代码集,他们插入可有浏览器显示的网页文件中.浏览器的作用是解释标记代码,并渲染页面供用户浏览. -每一个独立的标记代码都称为一个元素或者标记.大部分标记还可以使用属性进一步描述其功能. 原文地址:https://w

android 开发概述以及相关背景知识

参考链接:http://www.runoob.com/android/android-architecture.html http://www.runoob.com/android/android-application-components.html Android 架构 Android 操作系统是一个软件组件的栈,在架构图中它大致可以分为五个部分和四个主要层. Linux内核 在所有层的最底下是 Linux - 包括大约115个补丁的 Linux 3.6.它提供了基本的系统功能,比如进程管理

.NET 同步与异步之锁(Lock、Monitor)(七)

本随笔续接:.NET同步与异步之相关背景知识(六) 在上一篇随笔中已经提到.解决竞争条件的典型方式就是加锁 ,那本篇随笔就重点来说一说.NET提供的最常用的锁 lock关键字 和 Monitor. 一.lock关键字Demo public object thisLock = new object(); private long index; public void AddIndex() { lock (this.thisLock) { this.index++; if (this.index >

扫盲 HTTPS 和 SSL/TLS 协议[1]:背景知识、协议的需求、设计的难点

转自: https://program-think.blogspot.com/2014/11/https-ssl-tls-1.html 扫盲 HTTPS 和 SSL/TLS 协议[1]:背景知识.协议的需求.设计的难点 文章目录 ★相关背景知识★HTTPS 协议的需求是啥?★设计 HTTPS 协议的主要难点★结尾 ★相关背景知识 要说清楚 HTTPS 协议的实现原理,至少需要如下几个背景知识.1. 大致了解几个基本术语(HTTPS.SSL.TLS)的含义2. 大致了解 HTTP 和 TCP 的关

关于Web开发里并发、同步、异步以及事件驱动编程的相关技术

一.开篇语 我的上篇文章<关于如何提供Web服务端并发效率的异步编程技术>又成为了博客园里“编辑推荐”的文章,这是对我写博客很大的鼓励,也许是被推荐的原因很多童鞋在这篇文章里发表了评论,有童鞋说我这篇文章理论化很严重,没有实际代码和具体项目做支撑,这个评论让我有种理论和实践脱节的味道,所以我想在这里谈谈我为什么要写这篇文章的原因,这篇文章是把我前不久学习多线程编程的一个总结. 当我从我书堆里找到所有与多线程开发相关的书籍简单阅读后,我发现了一个问题,在java里开发多线程最强有力的实践就是做服

IOS多线程知识总结/队列概念/GCD/主队列/并行队列/全局队列/主队列/串行队列/同步任务/异步任务区别(附代码)

进程:正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间 线程:线程是进程中一个独立的执行路径(控制单元);一个进程中至少包含一条线程,即主线程 队列 dispatch_queue_t,队列名称在调试时辅助,无论什么队列和任务,线程的创建和回收不需要程序员操作,有队列负责. 串行队列:队列中的任务只会顺序执行(类似跑步) dispatch_queue_t q = dispatch_queue_create(“....”, DISPATCH_QUEUE_SER

Java基础知识强化之多线程笔记07:同步、异步、阻塞式、非阻塞式 的联系与区别

1. 同步: 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.但是一旦调用返回,就必须先得到返回值了. 换句话话说,调用者主动等待这个"调用"的结果. 对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已. 2. 异步: 所谓异步,"调用"在发出之后,这个调用就直接返回了,所以没有返回结果. 换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果.而是在"调用"发出后,"被调用者&q

Ajax知识笔记——入门,同步和异步,XHR

Ajax全称:Asynchronous Javascript and XML ,异步的javascript和XML. Ajax不是一种语言,是一种无需重新加载整个网页的情况下,能更新部分网页的技术. (与后台交互,实现局部更新,异步更新) 同步和异步: 同步(Ajax出现之前):客户端发起请求,服务端对请求进行处理和响应,这期间客户端一直在等待服务器端的响应,得到服务器端的响应之后客户端重新载入页面,这时候如果你有错误,只能再次发起请求,再次等待-- 异步(Ajax出现之后):XMLHttpRe

Python 中的进程、线程、协程、同步、异步、回调

进程和线程究竟是什么东西?传统网络服务模型是如何工作的?协程和线程的关系和区别有哪些?IO过程在什么时间发生? 在刚刚结束的 PyCon2014 上海站,来自七牛云存储的 Python 高级工程师许智翔带来了关于 Python 的分享<Python中的进程.线程.协程.同步.异步.回调>. 一.上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术. 不过首先说明一点术语.当我们说"上下文"的时候,指的是程序在执行中的一个状态.通常我们会用调用栈来表示这个状