C#深入多线程
主线程:
th = Thread.CurrentThread; //现在的线程为主线程
th.Name = "MainThread"; //set线程名字:主线程本身没有名字
thread1.Text += th.Name; //get线程名字
创建线程:
//创建线程
ThreadStart thread_action = new ThreadStart(ThreadAction); //方法/写法一
Thread new_thread = new Thread(thread_action);
new_thread.Start(); new Thread(ThreadAction).Start(); //方法二:自动转换成ThreadStart
new Thread(() => ThreadAction()); //方法三:使用lambda表达式 public static void ThreadAction()
{
Console.WriteLine("New Thread will do.");
}
创建带参数的线程:
ParameterizedThreadStart parameterizedThreadStart = new ParameterizedThreadStart(testBoy);
Thread new_thread = new Thread(parameterizedThreadStart);
new_thread.Start("hello"); //这样只能指定一个参数 new Thread(testBoy).Start("hello");
new Thread(() => testBoy("hello baby")).Start(); //这start就不要写参数了,不然会抛出异常的;这样写的好处是可以有多个参数 static void testBoy(object girl)
{
Console.WriteLine(girl);
}
暂停线程:
Thread.Sleep(); //让当前线程sleep,单位ms
等待线程(等待与暂停不一样):
等待:当前线程,等待调用Join的线程执行完毕。暂停:暂停调用Sleep的线程。
销毁线程(在定义线程引用thread的地方,可以调用thread.Abort方法):
thread.Abort(); //用Thread.ResetAbort();取消当前线程的Abort
如果线程已经Start、Abort,再次Start,则会抛出异常System.Threading.ThreadStateException。
判断线程的状态:
Console.WriteLine(t.ThreadState); //判断的是线程的生命周期的状态;t.IsAlive是执行的状态
线程优先级:
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(); //把所有的线程放在单个CPU上运行(便于测试看到效果)
t.Priority = ThreadPriority.Lowest; //可以get、set优先级
多个线程操作同一个对象时——加锁:
static void Main()
{
Console.WriteLine("Incorrect counter"); //先给出一个不加锁的,错误处理
Counter c = new Counter();
Thread t1, t2;
t1 = new Thread(() => TestCounter(c));
t2 = new Thread(() => TestCounter(c));
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.WriteLine("Total count: {0}", c.Count);
Console.WriteLine("-------------------"); Console.WriteLine("Correct counter"); //然后再加锁进行试验
CounterWithLock c1 = new CounterWithLock();
t1 = new Thread(() => TestCounter(c1));
t2 = new Thread(() => TestCounter(c1));
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.WriteLine("Total count: {0}", c1.Count);
t1.Abort();
t2.Abort();
//因为如果不加锁:假设当前对象的Count是10,那么可能线程1正在+1,得到11,还没有保存;与此同时线程2也在+1,也得到11。于是最后保存的结果就是11;但是按道理应该是12的 —— 错误原因
//加了锁:lock另外一个对象,于是一个线程访问该对象时,其他线程是无法访问的,直到该线程访问完毕 —— 因此不会出现上面的情况
}
static void TestCounter(CounterBase c)
{
for(int i = ; i < ; i++)
{
c.Decrement();
c.Increment();
}
}
以上做法,可能会造成死锁(例如有两把锁lock1、lock2:线程1先锁住了lock1,想要试图锁住lock2,却在此之前先Sleep较长时间,此时线程2趁机锁住lock2 —— 死锁产生:因为现在线程2是不能访问lock1的,如果线程2要访问lock1,则会等待线程1释放lock1;然而线程1在释放lock1之前,会先度过休眠期,然后访问lock2,但是也不行。故线程1、2都陷入不断等待的状态,即死锁状态(有一点还不明白,因为是线程,不像进程一样会分配大量资源,因此死锁也不会降低太多速度)。用代码解决死锁问题(先看下面的代码,再考虑这些问题):
static void Main()
{
object lock1 = new object();
object lock2 = new object(); //为了避免死锁导致后面的程序无法执行,先使用可以断开deadLock的方式
new Thread(() => LockTooMuch(lock1, lock2)).Start();
lock (lock2)
{
Thread.Sleep();
//TryEnter的用法(TryEnter就是try{Enter})
Console.WriteLine("Monitor.TryEnter allows not to get stuck, returning false after a specified timeout is elapsed");
if(Monitor.TryEnter(lock1, TimeSpan.FromSeconds())) //由于上面始终锁住lock1不放,故这里等多久都只能false
{
Console.WriteLine("Acquired a protected resource successfully");
}
else
{
Console.WriteLine("Timeout acquiring a resource!");
}
}
//现在直接访问,肯定就deaLock啦
new Thread(() => LockTooMuch(lock1, lock2)).Start();
lock(lock2)
{
Thread.Sleep();
lock(lock1)
{
Console.WriteLine("Acquired a protected resource successfully");
}
Console.WriteLine("在前面已经锁住了,所以后面就不用写什么else了");
}
}
static void LockTooMuch(object lock1, object lock2)
{
lock(lock1)
{
Thread.Sleep();
lock (lock2) ;
}
}
C#深入多线程的更多相关文章
- Python中的多进程与多线程(一)
一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...
- 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- Java多线程
一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程:进程 ...
- .NET基础拾遗(5)多线程开发基础
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...
- Java多线程基础——对象及变量并发访问
在开发多线程程序时,如果每个多线程处理的事情都不一样,每个线程都互不相关,这样开发的过程就非常轻松.但是很多时候,多线程程序是需要同时访问同一个对象,或者变量的.这样,一个对象同时被多个线程访问,会出 ...
- C#多线程之线程池篇3
在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...
- C#多线程之线程池篇2
在上一篇C#多线程之线程池篇1中,我们主要学习了如何在线程池中调用委托以及如何在线程池中执行异步操作,在这篇中,我们将学习线程池和并行度.实现取消选项的相关知识. 三.线程池和并行度 在这一小节中,我 ...
- C#多线程之线程池篇1
在C#多线程之线程池篇中,我们将学习多线程访问共享资源的一些通用的技术,我们将学习到以下知识点: 在线程池中调用委托 在线程池中执行异步操作 线程池和并行度 实现取消选项 使用等待句柄和超时 使用计时 ...
- C#多线程之线程同步篇3
在上一篇C#多线程之线程同步篇2中,我们主要学习了AutoResetEvent构造.ManualResetEventSlim构造和CountdownEvent构造,在这一篇中,我们将学习Barrier ...
随机推荐
- C# 调整控件的Z顺序
当窗口或者容器控件中的控件在布局过程中发生重叠的时候,会出现层次性.Z顺序较大的控件会遮挡Z顺序较小的控件,放在顶层的控件会挡住放在底层的控件. 1.编辑一个这样的窗口(使用Label控件) 2.添加 ...
- 转:C# 对委托的BeginInvoke,EndInvoke 及Control 的BeginInvoke,EndInvoke 的理解
转载自:http://www.cnblogs.com/easyfrog/p/3141269.html using System; using System.Collections.Generic; u ...
- git使用,多分支合并代码解决冲突,git删除远程分支,删除远程master默认分支方法
git使用,多分支合并代码解决冲突,git删除远程分支,删除远程master默认分支方法提交代码流程:1.先提交代码到自己分支上2.切换到devlop拉取代码合并到当前分支3.合并后有变动的推送到自己 ...
- Node.js中环境变量process.env详解
Node.js中环境变量process.env详解process | Node.js API 文档http://nodejs.cn/api/process.html官方解释:process 对象是一个 ...
- Django框架----路由系统(详细)
Django的路由系统 Django 1.11版本 URLConf官方文档 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表. ...
- IE haslayout的属性及其值
haslayout是IE 渲染引擎的一个内部组成部分.在IE 中,一个元素要么自己对自身的内容进行计算大小和组织,要么依赖于父元素来计算尺寸和组织内容.为了调节这两个不同的概念,渲染引擎采用了hasl ...
- Powerpoint 演示时定时提醒工具
经常碰到这样的场景,规定的演讲报告时间所剩无几,甚至是已经超时,但演讲者并不知情,做为主持人只能从旁边轻轻的善意的提醒,但有时演讲者会没注意到主持人的提醒... 这里要介绍的就是这样一款用于提醒演讲者 ...
- linux下nginx编译安装
步骤: 1.获取nginx安装包. 进入nginx官网:http://nginx.org/ 找到稳定版本: 点击红框内的链接. 使用wget获取安装包. wget http://nginx.org/d ...
- 被fancybox坑的心路历程
今天项目中需要使用fancybox来展示图片,但是使用中发现fancybox没起作用,点击图片直接刷新了页面! fancybox的原理是通过给a标签绑定事件,使得a标签不在是直接跳转链接,而是把链接中 ...
- SaaS教父:我眼中最糟糕的9条SaaS建议(转)
文章摘要:美国SaaS行业的教父级人物Jason Lemkin近日总结了在他眼里最糟糕的9条SaaS方面的建议,希望对SaaS行业的创业者有所启发. SaaS行业的创业者平时肯定会收到外界各种各样的建 ...