对锁而言,尽可能得使用父对象(级别更大得对象内容)。
通知
是指一个线程告诉另一个线程等待另一个线程回馈结果的操作。
如果没有得到反馈该线程会一直等待,直到另一个线程反馈为止。
通知一般使用Join方法,也可以使用同步类对象
同 步 基 元说 明Monitor监视器,支持锁定操作,防止一个或多个线程同时访问资源Mutex互斥器,支持锁定操作,防止一个或多个线程同时访问资源ReaderWriterLock读写锁,支持锁定操作,定义支持单个写线程和多个读线程的锁Semaphore信号量,也叫信号灯,阻塞线程直到另一个线程信号通知AutoResetEvent事件类,支持通知同步,阻塞线程直到另一个线程设置事件ManualResetEvent事件类,支持通知同步,阻塞线程直到另一个线程设置事件AutoResetEvent 类
通知正在等待的线程已发生事件
提供一种通知机制,可以控制线程执行的先后顺序
AutoResetEvent 类/ManualResetEvent类的重要方法
方 法说 明Set设置并发送信号Reset重置信号,也就是使信号无效WaitOne等待一个信号,如果没有信号到来则等待ManualResetEvent.WaitAny静态方法,等待一个信号数组,信号数组里面有任何信号到都可以,否则等待ManualResetEvent.WaitAll静态方法,等待一个信号数组,信号数组里面的信号全部到齐才可以,否则等待创建AutoResetEvent对象
AutoResetEvent myResetEvent = new AutoResetEvent(false);
参数说明:
false表示事件开始是无信号状态,
当参数为true表示创建的事件开始是有信号的,就相当于使用false参数创建事件后立即调用了Set方法。
俗称信号灯
orderEvent.WaitOne() //等待信号,一直等
orderEvent.Set() //发出信号,等待的子线程执行
现状
创建和销毁线程代价高
线程池
线程池是系统自己维护的线程的集合。
线程池技术减少频繁的线程创建与销毁对系统性能的影响
对于每一个进程系统都会给其创建一个线程池
如果想要执行线程操作,只需要向线程池发出一个执行某个操作的请求即可。
•1) 最小线程数,线程池的线程总大于等于这个值,一般这个值设置为逻辑CPU数,也就是能充分利用CPU同时执行这些线程。
•2) 最大线程数,默认1000,不建议修改这个值,如果这个值过小,很可能运行的线程的都被阻塞,而排队的线程永远得不到执行。
•3) 线程池是非常智能的,并不会发现可用线程不够马上创建新的线程,而是会有一个延迟以确保真的需要新的线程来补充(因为也不建议线程池中的方法执行时间太长比如超过500毫秒,影响线程池的判断)。线程池的目的就是减少实际线程的创建和回收,重复利用线程来做不同的工作。
ThreadPool
线程池静态类
托管线程池中的线程为后台线程,即它们的 IsBackground 属性为 true。这意味着在所有的前台线程都已退出后,ThreadPool 线程不会让应用程序保持运行。
原型: static bool QueueUserWorkItem( WaitCallback callBack, Object state )
举例: WaitCallback callBackCheck=new WaitCallback(this.Check); ThreadPool.QueueUserWorkItem(callBackCheck,info);
参数WaitCallback原型 委托 public delegate void WaitCallback (Object state);
线程池的一些重要知识
ThreadPool中的Thread不能手动取消,也不用手动开始。所以ThreadPool并不适用比较长的线程。只需要把一个 WaitCallback委托塞给ThreadPool,然后剩下的工作将由系统自动完成。系统会在ThreadPool的线程队列中一一启动线程。
当线程池满时,多余的线程会在队列里排队,当线程池空闲时,系统自动调入排队的线程,以保持系统利用率。
当需要复杂的同步技术,例如事件,或需要对一个线程调用Join方法时线程池就不能满足需求了.
以下情况中不宜使用ThreadPool而应该使用单独的Thread: 1.需要为线程指定详细的优先级 2.线程执行需要很长时间 3.需要前台线程。 4.在线程执行中需要对线程操作,如打断,挂起等
进程和线程相关概述
进程就是一个正在执行的应用程序。是系统进行资源分配的基本单位。
线程是在进程的内部执行的指令序列,共享进程的内存和系统资源。
多线程编程概述
v**.Net****下如何创建线程**
Thread
线程的不同状态
ThreadState
线程同步技术
加锁:lock,monitor
通知:AutoResetEvent
线程池
类的扩展方法的简单使用:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO.Ports; using System.Runtime.CompilerServices; namespace day31test03 { class Program { /// <summary> /// 扩展方法 /// </summary> /// <param name="args"></param> static void Main(string[] args) { //SerialPort port = new SerialPort(); Test test = new Test(); test.ddd(4, 5); test.add(4, 5); } } class Test { public void add(int a, int b) { Console.WriteLine(a+b); } } static class T { public static int ddd(this Test t, int x, int y) { return 2*(x - y); } } }并行的多线程,让CPU多个核都能跑起来。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace day31test05 { class Program { /// <summary> /// 并行的多线程 /// 多任务 /// </summary> /// <param name="args"></param> static void Main(string[] args) { Action action = new Action(Dowork); System.Threading.Tasks.Task task = new Task(action); task.Start(); Action action1 = new Action(Dowork); System.Threading.Tasks.Task task1 = new Task(action1); task1.Start(); Console.Read(); } public static void Dowork() { do { } while (true); } } }匿名方法委托,并行for和foreach
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace day31test06 { class Program { /// <summary> /// 基于匿名方法的多线程 /// 避免了委托 /// </summary> /// <param name="args"></param> static void Main(string[] args) { /*System.Threading.Thread t3 = new System.Threading.Thread(a => { Console.WriteLine("基于匿名方法的多线程"); }); t3.Start();*/ //并行for,特点:快 //System.Threading.Tasks.Parallel.For(0, 100, a => { System.Threading.Thread.Sleep(100); Console.WriteLine(System.DateTime.Now); }); //并行foreach,特点: String[] str = { "1" , "s", "w"}; System.Threading.Tasks.Parallel.ForEach(str, (item, kk) => { Console.WriteLine(item); }); Console.Read(); } } }