上条笔记说的内存共享冲突后,可以使用锁来解决
通过锁住对象内存,只能允许同一时间只有一个线程可以访问,其他想要访问的线程排队等待
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) 获取线程(委托方法)的返回值