C# 多线程系列(一)
线程是怎样工作的
1.多线程由一个线程调度器来进行内部管理,一个功能是CLR常常委托给操做系统。
一个线程调度器确保所有激活的线程在执行期间被合适的分配,等待或者阻塞的线程(比如,一个独占锁或者等待用户输入)不占用CPU资源。
2.在单核电脑上,一个线程调度器让时间片在每一个激活的线程中切换。在windows操作系统下,线程切换的时间分片通常为10微秒,远远大于CPU的开销时间(通常小于1微秒)。
3.在一个多核的电脑上,多线程实现了一个混合的时间片和真正的并发,不同的线程同时在不同的CPU上执行代码。还是存在某些时间片,因为操作系统需要服务它自己的线程,包括其他的应用的线程。
4.当一个线程的执行被内部因素打断,比如时间片,则说这个线程是抢占式的。在大部分情形下,一个线程不能控制自己何时何地被抢占。
进程与线程
线程并行运行在一个单独的进程中。进程之间是完全隔离的;线程在一定程度上隔离。运行在同一个应用程序下的线程共享堆内存。
进程间的切换:
先加载程序A的上下文,然后开始执行A,保存程序A的上下文,调入下一个要执行的程序B的程序上下文,然后开始执行B,保存程序B的上下文。。。
线程间的切换:
先加载程序A的上下文,然后执行A的A1线程,再执行A的A2线程。。。保存程序A的上下文;
1.线程结束无法重启
class Program
{
static void Main(string[] args)
{
Thread thread = new Thread(threadOne);
thread.Start();
Thread.Sleep(5000);
//thread.Start();打开报错
} static void threadOne()
{
for(int i=0; i<100; i++)
{
lib.put("t"+i);
Thread.Sleep(10);
}
}
}
一旦开始,一个线程的IsAlive属性返回true,直到这个线程结束。当传递给线程的构造函数的委托完成执行时,这个线程结束。一旦结束,这个线程不能重启。
2.内存隔离
class Program
{
static void Main(string[] args)
{
Thread thread = new Thread(threadOne);
thread.Start();
threadOne();//主线程调用
Thread.Sleep(5000);
//thread.Start();打开报错
} static void threadOne()
{
for(int i=0; i<10; i++)
{
lib.put("t");
Thread.Sleep(10);
}
}
}
CLR给每个线程分配自己内存栈,因此局部变量可以保持分离。所以两次调用threadOne都正常打印了10个"t"。
3. 数据共享
class Program
{
static bool bDone = false;
static void Main(string[] args)
{
Thread thread = new Thread(threadOne);
thread.Start();
threadOne();
Console.ReadKey();
} static void threadOne()
{
if(!bDone)
{
bDone = true;
lib.put("threadOne");
}
}
}
如果多个线程对同一个对象实例有相同的引用,这些线程就共享这个对象实例的数据。所以只会输出一个threadOne。
4.线程安全
上述例子,是有可能打印出两次threadOne的。当bDone被置成true之前,若主线程和子线程都已经通过if判定,将打印两次。
static void threadOne()
{
if(!bDone)
{
Thread.Sleep();//加上sleep后,会出现主线程和子线程都通过if判定后才把bDone置成true,所以打印两次threadOne,
bDone = true;
lib.put("threadOne");
}
}
改进方式当读\写一个公共字段时,获取一个独占锁(exclusive lock)。C#提供了关键字lock。
class Program
{
static bool bDone = false;
static readonly object locker = new object();
static void Main(string[] args)
{
Thread thread = new Thread(threadOne);
thread.Start();
threadOne();
Console.ReadKey();
} static void threadOne()
{
lock (locker)
{
if (!bDone)
{
Thread.Sleep();
bDone = true;
lib.put("threadOne");
}
}
}
}
当两个线程同时抢占一个锁时(在这个例子中,locker),一个线程等待,或者阻塞,直到这个锁释放。在这个例子中,这个锁保证一次只有一个线程可以进入代码的临界区域,然后“threadOne”只会被打印一次。代码在这种不确定的多线程背景下中被保护被叫做线程安全。
lock关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。在块的开始处调用 Enter,而在块的结尾处调用 Exit。这样可确保当一个线程位于代码的关键部分时,另一个线程不会进入该关键部分。 如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。一个线程,当阻塞的时候,不占用CPU资源。
5.Join和Sleep
Join是一种同步方法,阻止调用线程 (即,调用的方法的线程),直到线程其Join方法调用已完成。 使用此方法以确保线程已终止。 如果线程不会终止,调用方将无限期阻止。
Join有多个重载方法,可以在Join方法中添加一个参数,milliseconds或者timeSpan。如果这个线程结束了则Join方法返回true,如果这个线程超时则返回false,但不结束该线程。
static void Main(string[] args)
{
Thread thread = new Thread(threadOne);
thread.Start();
thread.Join();//等到thread线程结束后继续本线程
lib.print("end");
Console.ReadKey();
} static void threadOne()
{
lib.print("threadOne");
Thread.Sleep();
}
Sleep暂停当前线程一段指定的时间。
Thread.Sleep(TimeSpan.FromHours(1));//sleep一个小时
Thread.Sleep(500);//500 线程被阻塞的毫秒数。 指定零0以指示应挂起此线程以使其他等待线程能够执行。
当使用Sleep或Join暂停线程时,这个线程是阻塞的,不消耗CPU资源。
C# 多线程系列(二)
C# 多线程系列(一)的更多相关文章
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例
概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...
- Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock
本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...
- Java多线程系列--“JUC锁”01之 框架
本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...
- Java多线程系列目录(共43篇)
最近,在研究Java多线程的内容目录,将其内容逐步整理并发布. (一) 基础篇 01. Java多线程系列--“基础篇”01之 基本概念 02. Java多线程系列--“基础篇”02之 常用的实现多线 ...
- Java多线程系列--“JUC线程池”06之 Callable和Future
概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...
- Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例
概要 前面对"独占锁"和"共享锁"有了个大致的了解:本章,我们对CountDownLatch进行学习.和ReadWriteLock.ReadLock一样,Cou ...
- Java多线程系列--“JUC锁”06之 Condition条件
概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...
- Java多线程系列--“JUC锁”05之 非公平锁
概要 前面两章分析了"公平锁的获取和释放机制",这一章开始对“非公平锁”的获取锁/释放锁的过程进行分析.内容包括:参考代码获取非公平锁(基于JDK1.7.0_40)释放非公平锁(基 ...
随机推荐
- Haproxy 【转载】
一.HAProxy简介 (1)HAProxy 是一款提供高可用性.负载均衡以及基于TCP(第四层)和HTTP(第七层)应用的代理软件,支持虚拟主机,它是免费.快速并且可靠的一种解决方案. HAProx ...
- Thesis Viva checklist
This list gives you suggestions helpful in preparing to defend your thesis: I know my thesis thoroug ...
- PAT 1093. Count PAT's
The string APPAPT contains two PAT's as substrings. The first one is formed by the 2nd, the 4th, and ...
- eclipse 快捷键及使用技巧
一.程序的编译和运行的环境配置(一般不改) window -- Preferences -- Java 编译环境:Compiler 默认选中的就是最高版本. 运行环境:Installed JREs 默 ...
- 【codeforces 801A】Vicious Keyboard
[题目链接]:http://codeforces.com/contest/801/problem/A [题意] 一个字符串只由VK组成; 让你修改一个字符; 使得剩下的字符串里面子串VK的个数最大; ...
- sencha touch 2中判断游览器是否包含webkit的方法
<script type="text/javascript"> if (!Ext.browser.is.WebKit) { alert("The curren ...
- [bzoj4385][POI2015]Wilcze doły_单调队列
Wilcze doły bzoj-4385 POI-2015 题目大意:给定一个n个数的序列,可以将连续的长度不超过d的区间内所有数变成0,求最长的一段区间,使得区间和不超过p. 注释:$1\le n ...
- MVC.Net 5:允许保存和输出Html内容
当我们在保存表单内容时,如果其中有一项内容包含Html的tag时,系统会报如下错误: A potentially dangerous Request.Form value was detected f ...
- 027依据前序遍历和中序遍历,重建二叉树(keep it up)
剑指offer中题目:http://ac.jobdu.com/problem.php?pid=1385 题目描写叙述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.如果输入的前序遍历和中 ...
- 从头认识java-15.6 队列(Queue)
这一章节我们来讨论一下队列(Queue). 1.什么是队列? 队列是一种特殊的线性表,特殊之处在于它仅仅同意在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样.队列是 ...