上条笔记说的内存共享冲突后,可以使用锁来解决
通过锁住对象内存,只能允许同一时间只有一个线程可以访问,其他想要访问的线程排队等待
static void CallFunc(object obj) { Class1 o = obj as Class1; lock (o) { while (true) { o.Cooo(); } } }
使用lock关键字,申请o对象的内存访问,如果没有线程在访问,则锁住对象,进行里面的代码。如果对象已经被锁了,那么排队等待。
class Class1 { public int i = 5; public void Cooo() { this.i++; if (this.i == 5) { Console.WriteLine("我可能会被输出"); } this.i = 5; } } static void CallFunc(object obj) { Class1 o = obj as Class1; while (true) { o.Cooo(); } } Class1 c = new Class1(); Thread go1 = new Thread(CallFunc); go1.Start(c); Thread go2 = new Thread(CallFunc); go2.Start(c);
此时,“我可能会被输出”真的会输出
从程序设计来看,这句话是不可能被输出的
但是,这里开启两个线程后,共享了这份内存
时间线变成了两条,不在是顺着,有可能在i++之后,另一个线程修改i=5,此时再到回到这个线程,判断i确实=5
static void First() { Console.WriteLine(2017); Console.WriteLine("First End"); } static void Second(Task t) { Console.WriteLine("Second End"); } static void Third(Task t) { Console.WriteLine("Third Start"); Thread.Sleep(2000); Console.WriteLine("Third End"); } Task t = new Task(First); Task t2 = t.ContinueWith(Second); Task t3 = t.ContinueWith(Third); t.Start(); while (true) { Console.WriteLine(t.Status); Thread.Sleep(500); }
使用new Task创建一个任务,通过这个任务的ContinueWith方法来创建连续任务,返回Task
就是在t任务完成后,t2和t3就开始异步执行
同理的,t2,t3也可以通过ContinueWith来创建他们的后续任务
static void test1() { Console.WriteLine("test1 1231321"); } static void test2() { Console.WriteLine("test2"); } //任务开启线程 Task tas = new Task(test1); tas.Start(); TaskFactory tf = new TaskFactory(); Task tass = tf.StartNew(test2);
TaskFactory 是任务工厂(工厂模式)
通过StartNew()创建并开始一个任务
static void Thread3(object state) { Console.WriteLine("线程开始:"+Thread.CurrentThread.ManagedThreadId); Thread.Sleep(100); Console.WriteLine("线程结束"); } ThreadPool.QueueUserWorkItem(Thread3); ThreadPool.QueueUserWorkItem(Thread3);
直接通过ThreadPool静态类的QueueUserWorkItem方法传入要开启线程的方法,它内部会使用线程来执行
Thread.CurrentThread.ManagedThreadId获取当前线程id
一个应用程序最多只能有一个线程池,
通过ThreadPool静态类的QueueUserWorkItem()方法传入工作函数来排入线程池。
ThreadPool内部管理线程,是否开启新的线程还是使用旧的线程来完成(会检查有没有空闲的,没有先等待一下,再没有再创建新的)
线程池开启的线程,不受我们控制了。
class ThreadClass { private int a; private int b; private int sum; public ThreadClass(int a,int b) { this.a = a; this.b = b; } public void sumThread() { this.sum = a + b; } public int getResult() { return this.sum; } } ThreadClass tc = new ThreadClass(100 , 150); Thread tcTh = new Thread(tc.sumThread); tcTh.Start(); tcTh.Join();//等待线程完成 Console.WriteLine(tc.getResult());
可以看出,Thread线程参数接受静态方法,也接受成员方法
tcTh.Join() 表示等待线程完成,再运行下面的代码
static void Thread2(object a) { int[] s = a as int[]; int result = s[0] + s[1]; Console.WriteLine("结果为:" + result); } using System.Threading; Thread thread = new Thread(Thread2); thread.Start(new int[] { 5, 8 });
通过Thread类开启一个线程,传递一个没有返回值的方法
该方法最多只能有一个参数并且类型为object的
Thread类在 System.Threading里面
static int Thread1(int a,int b) { Console.WriteLine("Thread1"); return a + b; } static void CallBack(IAsyncResult ar) { Func<int, int, int> th = ar.AsyncState as Func<int, int, int>; int result = th.EndInvoke(ar); Console.WriteLine("结果为:" + result); } Func<int, int, int> th = Thread1; th.BeginInvoke(9, 10, CallBack, th);
IAsyncResult ar为回调自动传参
通过AsyncState获取BeginInvoke方法最后一个参数传入的数据
static int Thread1(int a,int b) { Console.WriteLine("Thread1"); return a + b; } Func<int, int, int> th = Thread1; th.BeginInvoke(5, 3, ar => { int result = th.EndInvoke(ar); Console.WriteLine("结果:" + result); }, null);
ar是IAsyncResult类型自动传给回调函数的
EndInvoke(ar) 获取线程(委托方法)的返回值