1、单线程

Thread.CurrentThread 获取当前线程

Thread.CurrentThread.ManagedThreadId 获取当前线程ID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
internal class Program2
{
private static void Main2(string[] args)
{
{//同步单线程方法: 按顺序执行,每次调用完成后才能进入下一行,是同一个线程运行
Console.WriteLine();
Console.WriteLine("***********同步方法 statr,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
int j = 0;
int k = 1;
int m = j + k;
for (int i = 0; i < 5; i++)
{
string name = string.Format("{0}_{1}", "同步方法", i);
DosomethingLong(name);
}
Console.WriteLine("***********同步方法 end,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
}

}
private static void DosomethingLong(string name)
{
Console.WriteLine("***************DosomethingLong start {0} 线程ID:{1} 时间:{2}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
long lResult = 0;
for (int i = 0; i < 100000000; i++)
{
lResult += i;
}
Console.WriteLine("***************DosomethingLong end {0} 线程ID:{1} {2} 时间:{3}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), lResult);
}
}

2、多线程

/任何的异步多线程都离不开委托delegate
//委托的异步调用异步
//多线程: 发起调用,不等待结束就直接进入下一行(主线程);
动作会由一个新线程来执行(子线程 ) 并发了

1、同步单线程方法卡界面——主(UI)线程忙于计算,所以不能响应

​ 异步多线程方法不卡界面—-计算任务交给子线程,主(UI)线程已经闲置,可以响应别的操作

​ cs:按钮后能不卡死–上传文件不卡死

​ bs: 用户注册发邮件/发短信/写日志

2、 同步单线程方法慢—因为只有一个线程计

​ 算异步多线程方法快—因为多个线程并发计算

​ 多线程就是用资源换性能,但并不是线性增长

​ 线程并不是越多越好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace 多线程异步
{
internal class Program
{
private static void Main(string[] args)
{
{
//任何的异步多线程都离不开委托delegate
//委托的异步调用异步
//多线程: 发起调用,不等待结束就直接进入下一行(主线程);
// 动作会由一个新线程来执行(新线程 );
Console.WriteLine();
Console.WriteLine("***********异步方法 statr,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);

//创建委托action
//Action<string> action = DosomethingLong;
// action.Invoke("异步方法1");
//action.Invoke("异步方法2");
// action.BeginInvoke("异步方法3", null, null);//异步调用
for (int i = 0; i < 5; i++) {
string name = $"异步方法_{i}";
action.BeginInvoke(name,null,null);

}
Console.WriteLine("***********异步方法 end,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
}
Console.ReadLine();

}
private static void DosomethingLong(string name)
{
Console.WriteLine("***************DosomethingLong start {0} 线程ID:{1} 时间:{2}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
long lResult = 0;
for (int i = 0; i < 100000000; i++)
{
lResult += i;
}
Console.WriteLine("***************DosomethingLong end {0} 线程ID:{1} 时间:{2} {3}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), lResult);
}
}
}

3、委托异步回调控制顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace 多线程异步
{
internal class 委托异步回调控制顺序
{
private static void Main(string[] args)
{
{
//任何的异步多线程都离不开委托delegate
//委托的异步调用异步
//多线程: 发起调用,不等待结束就直接进入下一行(主线程);
// 动作会由一个新线程来执行(新线程 );

Console.WriteLine();
Console.WriteLine("***********异步方法 statr,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);

Action<string> action = UpdataDB;

//异步回调 (会在线程执行完毕后运行)
AsyncCallback callback = ar=> {
Console.WriteLine(ar.AsyncState);//此处的值为:sunday1,用户自定义设置的值
Console.WriteLine("A操作完成了。。。线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
};
//传入的值 回调委托 自定义传入值(Object类型)
action.BeginInvoke("异步方法3", callback, "sunday1");


Console.WriteLine("***********异步方法 end,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
}
Console.ReadLine();

}

private static void UpdataDB(string name)
{
Console.WriteLine("***************UpdataDB start {0} 线程ID:{1} 时间:{2}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
long lResult = 0;
for (int i = 0; i < 100000000; i++)
{
lResult += i;
}
Console.WriteLine("***************UpdataDB end {0} 线程ID:{1} 时间:{2} {3}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), lResult);
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace 多线程异步
{
internal class 文件上传进度条展示
{
private static void Main(string[] args)
{
{
//任何的异步多线程都离不开委托delegate
//委托的异步调用异步
//多线程: 发起调用,不等待结束就直接进入下一行(主线程);
// 动作会由一个新线程来执行(新线程 );

Console.WriteLine();
Console.WriteLine("***********异步方法 statr,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);

#region MyRegion
/*Action<string> action = UpdataDB;
AsyncCallback callback = ar => {
Console.WriteLine(ar.AsyncState);

Console.WriteLine("A操作完成了。。。线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
};
*//*IAsyncResult asyncResult = action.BeginInvoke("文件上传", null, "sunday1");

int i = 0;
while (!asyncResult.IsCompleted)
{
if (i < 9)
{
ShowConsleAnview($"当前进度:{++i * 10}%");
}
else
{
Console.WriteLine("当前进度:99%");
}
Thread.Sleep(10);
}*//*


var asyncResult = action.BeginInvoke("调用接口", null, null);
asyncResult.AsyncWaitHandle.WaitOne();//阻塞当前线程,直到收到信号量
asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等等
//asyncResult.AsyncWaitHandle.WaitOne(1000);//阻塞当前线程 最多等待1000ms
Console.WriteLine("完成文件上传");*/
#endregion

#region 调用接口需要返回值
Func<int> func = RemoteService;

var asyncResult = func.BeginInvoke(null, null);//异步调用结果,描述异步操作的
int result = func.EndInvoke(asyncResult);//获取线程返回值
Console.WriteLine(result);
#endregion
Console.WriteLine("***********异步方法 end,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
}
Console.ReadLine();

}
private static void ShowConsleAnview(string text) {
Console.WriteLine(text);

}

private static void UpdataDB(string name)
{
Console.WriteLine("***************UpdataDB start {0} 线程ID:{1} 时间:{2}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
long lResult = 0;
for (int i = 0; i < 1000000000; i++)
{
lResult += i;
}
Console.WriteLine("***************UpdataDB end {0} 线程ID:{1} 时间:{2} {3}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), lResult);
}
private static int RemoteService() {
long lResult = 0;
for (int i = 0; i < 1000000000; i++)
{
lResult += i;
}
return ((int)lResult);
}
}
}

4、Thread操作线程各种APi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private static void Main(string[] args)
{
{
//任何的异步多线程都离不开委托delegate
//委托的异步调用异步
//多线程: 发起调用,不等待结束就直接进入下一行(主线程);
// 动作会由一个新线程来执行(新线程 );

Console.WriteLine();
Console.WriteLine("***********异步方法 statr,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);

ThreadStart threadStart = ()=> {
Console.WriteLine($"Thread Start {Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(2000);
Console.WriteLine($"Thread End {Thread.CurrentThread.ManagedThreadId}");
};
Thread thread = new Thread(threadStart);
//thread.IsBackground = true;
thread.Start();
//thread.Suspend();
//thread.Resume();
thread.Join();

//thread.Abort();


Console.WriteLine("***********异步方法 end,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
}
Console.ReadKey();
}

5、ThreadPool线程池的优势

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static void Main(string[] args)
{
Console.WriteLine();
Console.WriteLine("***********异步方法 statr,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);

//.NetFramework 2.0(新的CLR) ThreadPool:池化资源管理设计思想,线程是一种资源,
//之前每次要用线程,就去申请一个线程,使用完之后,释放掉;
//池化就是做一个容器,容器提前申请5个线程,
//程序需要使用线程,直接找容器获取,用完后再放回容器(控制状态),避免频繁的申请和销毁
//容器自己还会根据限制的数量去申请和释放
WaitCallback callback = (o) =>
{
Console.WriteLine($"Thread is ThreadPool Start {Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(2000);
Console.WriteLine($"Thread is ThreadPool End {Thread.CurrentThread.ManagedThreadId}");
};
ThreadPool.QueueUserWorkItem(callback);
Console.WriteLine("***********异步方法 end,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.ReadKey();
}

6、多线程Parallel的特点和控制线程数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private static void Main(string[] args)
{
Console.WriteLine();
Console.WriteLine("***********异步方法 statr,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);

//Parallel可以启动多线程,主线程也参与计算

Parallel.Invoke(() =>
{
Console.WriteLine($"Thread is Parallel Start1 {Thread.CurrentThread.ManagedThreadId}");

Console.WriteLine($"Thread is Parallel End1 {Thread.CurrentThread.ManagedThreadId}");
}, () =>
{
Console.WriteLine($"Thread is Parallel Start2 {Thread.CurrentThread.ManagedThreadId}");

Console.WriteLine($"Thread is Parallel End2 {Thread.CurrentThread.ManagedThreadId}");
}, () =>
{
Console.WriteLine($"Thread is Parallel Start3 {Thread.CurrentThread.ManagedThreadId}");

Console.WriteLine($"Thread is Parallel End3 {Thread.CurrentThread.ManagedThreadId}");
}, () =>
{
Console.WriteLine($"Thread is Parallel Start4 {Thread.CurrentThread.ManagedThreadId}");

Console.WriteLine($"Thread is Parallel End4 {Thread.CurrentThread.ManagedThreadId}");
});
Parallel.For(1, 10, o => { Console.WriteLine(o); });
Console.WriteLine("***********异步方法 end,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.ReadKey();
}

7、Task线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
private static void Main(string[] args)
{
{


Console.WriteLine();
Console.WriteLine("***********异步方法 statr,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);

Action action = () =>
{
Console.WriteLine($"Thread is Task Start1 {Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep( 1000 );
Console.WriteLine($"Thread is Task End1 {Thread.CurrentThread.ManagedThreadId}");
};
List<Task> taslList = new List<Task>();
Task task = new Task(action);
task.Start();//运行线程
taslList.Add(task);
taslList.Add(Task.Run(() => { DosomethingLong("阿莫"); }));//运行线程
taslList.Add(Task.Run(() => { DosomethingLong("杨帆"); }));
taslList.Add(Task.Run(() => { DosomethingLong("一路"); }));

//阻塞当前线程,直到任一任务结束----主线程被阻塞,所以卡界面
Task.WaitAny(taslList.ToArray());
Console.WriteLine("项目里程碑达成,收取20 % 的费用");

//既需要多线程来提升性能,又需要在多线程全部完成后才能执行的操作
Task.WaitAll(taslList.ToArray());//等待所有线程结束后才执行后面的操作
//阻塞当前线程,直到全部任务结束-----主线程被阻塞,所以卡界面

Console.WriteLine("***********异步方法 end,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
}
Console.ReadLine();

}
private static void DosomethingLong(string name)
{
Console.WriteLine("***************DosomethingLong start {0} 线程ID:{1} 时间:{2}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
long lResult = 0;
for (int i = 0; i < 100000000; i++)
{
lResult += i;
}
Console.WriteLine("***************DosomethingLong end {0} 线程ID:{1} 时间:{2} {3}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), lResult);
}

不会卡界面

1
2
3
4
5
6
7
8
9
10
11
12
//这样就不会卡界面了
Task.Run(() =>//意味着方法体里面的东西,由一个新的线程去执行
{//不是推荐做法,1 尽量不要线程套线程

//阻塞当前线程,直到任一任务结束----主线程被阻塞,所以卡界面
Task.WaitAny(taslList.ToArray());
Console.WriteLine("项目里程碑达成,收取20 % 的费用");

//既需要多线程来提升性能,又需要在多线程全部完成后才能执行的操作
Task.WaitAll(taslList.ToArray());//等待所有线程结束后才执行后面的操作
//阻塞当前线程,直到全部任务结束-----主线程被阻塞,所以卡界面
});

TaskFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
private static void Main(string[] args)
{
{


Console.WriteLine();
Console.WriteLine("***********异步方法 statr,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);

Action action = () =>
{
Console.WriteLine($"Thread is Task Start1 {Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000);
Console.WriteLine($"Thread is Task End1 {Thread.CurrentThread.ManagedThreadId}");
};
List<Task> taslList = new List<Task>();
Task task = new Task(action);
task.Start();
taslList.Add(task);
taslList.Add(Task.Run(() => { DosomethingLong("阿莫"); }));
taslList.Add(Task.Run(() => { DosomethingLong("杨帆"); }));
taslList.Add(Task.Run(() => { DosomethingLong("一路"); }));


TaskFactory taskFactory = new TaskFactory();
taskFactory.ContinueWhenAny(taslList.ToArray(), t => {
Console.WriteLine("XX第一个完成,获取红包奖励:{0}", Thread.CurrentThread.ManagedThreadId);
});
taslList.Add(taskFactory.ContinueWhenAll(taslList.ToArray(), tArry =>
{
Console.WriteLine("来个庆功宴,部署联调测试:{0}", Thread.CurrentThread.ManagedThreadId);
}));
//continue的后续线程,可能是新线程,可能是刚完成任务的线程,还可能是同一个线程

//这样就不会卡界面了
//Task.Run(() =>//意味着方法体里面的东西,由一个新的线程去执行
//{//不是推荐做法,1 尽量不要线程套线程

///阻塞当前线程,直到任一任务结束----主线程被阻塞,所以卡界面
Task.WaitAny(taslList.ToArray());
Console.WriteLine("项目里程碑达成,收取20 % 的费用");

//既需要多线程来提升性能,又需要在多线程全部完成后才能执行的操作
Task.WaitAll(taslList.ToArray());//等待所有线程结束后才执行后面的操作
//阻塞当前线程,直到全部任务结束-----主线程被阻塞,所以卡界面
//});

Console.WriteLine("***********异步方法 end,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
}
Console.ReadLine();

}
private static void DosomethingLong(string name)
{
Console.WriteLine("***************DosomethingLong start {0} 线程ID:{1} 时间:{2}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
long lResult = 0;
for (int i = 0; i < 100000000; i++)
{
lResult += i;
}
Console.WriteLine("***************DosomethingLong end {0} 线程ID:{1} 时间:{2} {3}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), lResult);
}

8、线程安全

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 internal class 多线程安全
{
private static void Main(string[] args)
{
{


Console.WriteLine();
Console.WriteLine("***********异步方法 statr,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
/*
for (int i = 0; i < 5; i++)
{
int k = i;
Task.Run(() =>
{
Console.WriteLine($"this is {i} {k} Start...{Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(2000);
//Task.Delay(1000);
Console.WriteLine($"this is {i} {k} End...{Thread.CurrentThread.ManagedThreadId}");
});
}*/
List<int> list = new List<int>();
for (int i = 0;i < 1000;i++)
{
//list.Add(i);
Task.Run(() =>//多线程之后,结果就变成小于10000--就是有的数据丢失了
{
list.Add(i);
});
}
//多线程安全问题:一段代码,单线程执行和多线程执行结果不一致,就表明有线程安全问题
//List是个数组结构,在内存上是连续摆放的,假如同一时刻,去增加一个数据,都是操作同一个内存 ?位置,2个cpu同时发了命令,内存先执行一个再执行一个,就出现覆盖
Thread.Sleep(5000);
Console.WriteLine(list.Count);
Console.WriteLine("***********异步方法 end,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
}
Console.ReadLine();

}
private static void DosomethingLong(string name)
{
Console.WriteLine("***************DosomethingLong start {0} 线程ID:{1} 时间:{2}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
long lResult = 0;
for (int i = 0; i < 100000000; i++)
{
lResult += i;
}
Console.WriteLine("***************DosomethingLong end {0} 线程ID:{1} 时间:{2} {3}****************", name, Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), lResult);
}
}

9、Lock锁解决线程安全

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private static readonly object LOCK=new object();
private static void Main(string[] args)
{
{
Console.WriteLine();
Console.WriteLine("***********异步方法 statr,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
List<int> list = new List<int>();
for (int i = 0; i < 1000; i++)
{
//list.Add(i);
Task.Run(() =>//多线程之后,结果就变成小于10000--就是有的数据丢失了
{
//Monitor.Enter(LOCK);
lock (LOCK)
{
list.Add (i);
}
//Monitor.Exit(LOCK);
});
}
//加lock 就能解决线程安全问题---就是单线程化--Lock就是保证方法块儿任意时刻只有一个线程能进去,其他线程就排队
//Lock原理---语法糖--等价于Monitor--锁定一个内存引用地址--所以不能是值类型--也不能是null
Thread.Sleep(1000);
Console.WriteLine(list.Count);
Console.WriteLine("***********异步方法 end,线程 ID:{0}", Thread.CurrentThread.ManagedThreadId);
}
Console.ReadLine();

}

10、Lock锁变量执行顺序

TestLOCk类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 单线程_Task
{
public class TestLock
{
private static readonly object Test_Lock = new object();
private static readonly object Test_LockTemp = new object();

public static void Show()
{
for (int i = 0; i < 5; i++)
{
Task.Run(() => {
lock (Test_Lock)
{
Console.WriteLine($"this is TestLock {i} Start...{Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(2000);
Console.WriteLine($"this is TestLock {i} End...{Thread.CurrentThread.ManagedThreadId}");
}
});
}
}
public void ShowTemp(int index)
{
for (int i = 0; i < 5; i++)
{
Task.Run(() => {
lock (Test_LockTemp)
{
Console.WriteLine($"this is TestLockShowTemp {i}--{index} Start...{Thread.CurrentThread.ManagedThreadId}");
// Thread.Sleep(2000);
Console.WriteLine($"this is TestLockShowTemp {i}--{index} End...{Thread.CurrentThread.ManagedThreadId}");
}
});
}
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
namespace 单线程_Task
{
internal class Lock锁变量执行顺序
{
private static readonly object LOCK = new object();
private static void Main(string[] args)
{
{
TestLock testLock1=new TestLock();
testLock1.ShowTemp(1);
TestLock testLock2 = new TestLock();
testLock2.ShowTemp(2);

/* TestLock.Show();
for (int i = 0; i < 5; i++)
{
Task.Run(() => {
lock (LOCK)
{
Console.WriteLine($"this is Main {i} Start...{Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(2000);
Console.WriteLine($"this is Main {i} End...{Thread.CurrentThread.ManagedThreadId}");
}
});
}*/
}
//假如我是希望主程序和方法是并发的,如果共用一个锁变量,就会出现相互阻塞
//锁不同的变量,才能并发的;
//单次调用内部肯定是加锁顺序执行---两个之间,能并发吗 Y/N
//Y---不同的实例里面 都是不同的字段所以要static
Console.ReadLine();

}
}
}

以上可并发

以下不能并发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private readonly string Test_LockString = "静待花开";
public void ShowString(int index)
{
for (int i = 0; i < 5; i++)
{
Task.Run(() => {
lock (Test_LockString)
{
Console.WriteLine($"this is TestLockShowString {i}--{index} Start...{Thread.CurrentThread.ManagedThreadId}");
// Thread.Sleep(2000);
Console.WriteLine($"this is TestLockShowString {i}--{index} End...{Thread.CurrentThread.ManagedThreadId}");
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private static readonly string LockString = "静待花开";
private static void Main(string[] args)
{
{

TestLock testLock1 = new TestLock();
testLock1.ShowString(1);

for (int i = 0; i < 5; i++)
{
Task.Run(() => {
lock (LockString)
{
Console.WriteLine($"this is Main {i}--{2} Start...{Thread.CurrentThread.ManagedThreadId}");
// Thread.Sleep(2000);
Console.WriteLine($"this is Main {i}--{2} End...{Thread.CurrentThread.ManagedThreadId}");
}
});
}


Console.ReadLine();

}

//单次调用内部肯定是加锁顺序执行—两个之间,能并发吗 Y/N

//N不能并发,锁定的是引用—字符串是享元的,堆里面只有一个“静待花开,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class TestLockGeneric<T>
{
private static readonly object Test_Lock = new object();


public static void Show(int index)
{
for (int i = 0; i < 5; i++)
{
Task.Run(() => {
lock (Test_Lock)
{
Console.WriteLine($"this is TestLockGeneric-{index} {i} Start...{Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(2000);
Console.WriteLine($"this is TestLockGeneric-{index} End...{Thread.CurrentThread.ManagedThreadId}");
}
});
}
}
private readonly object Test_LockTemp = new object();
public void ShowTemp(int index)
{
for (int i = 0; i < 5; i++)
{
Task.Run(() => {
lock (Test_LockTemp)
{
Console.WriteLine($"this is TestLockShowTemp {i}--{index} Start...{Thread.CurrentThread.ManagedThreadId}");
// Thread.Sleep(2000);
Console.WriteLine($"this is TestLockShowTemp {i}--{index} End...{Thread.CurrentThread.ManagedThreadId}");
}
});
}
}
private readonly string Test_LockString = "静待花开";
public void ShowString(int index)
{
for (int i = 0; i < 5; i++)
{
Task.Run(() => {
lock (Test_LockString)
{
Console.WriteLine($"this is TestLockShowString {i}--{index} Start...{Thread.CurrentThread.ManagedThreadId}");
// Thread.Sleep(2000);
Console.WriteLine($"this is TestLockShowString {i}--{index} End...{Thread.CurrentThread.ManagedThreadId}");
}
});
}
}
}
1
2
3
4
5
6
7
8
{
TestLockGeneric<int>.Show(1);
TestLockGeneric<int>.Show(2);
TestLockGeneric<TestLock>.Show(3);
//单次调用内部肯定是加锁顺序执行--- 1和2直接能并发吗 1和3之间能并发吗YY NN YN NY
//1和2不能并发 因为是相同的变量--泛型类,在类型参数相同时,是同一个类
//1和3可以并发 因为是不同的变量--泛型类,在类型参数不同时,是不同的类
}

11、await Asyn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;

namespace AwatAsync
{
/// <summary>
/// await/async:是个新语法,出现C#5.0NetFramework在4.5及以上(CLR4.0)
/// 是一个语法糖,不是一个全新的异步多线程使用方式,
/// (语法糖:就是编译器提供的新功能)
/// 本身并不会产生新的线程,但是依托于Task而存在,所以程序执行时 也是有多线程的
///async可以随便添加,可以不用await
///await只能出现在task,但是方法必须声明async 不能单独出现
///
/// await/async之后,原本没有返回值的可以这回Task
/// 原本返回 X类型的,可以返回Task<X>
///有点反人类,不过暂时先记住
/// </summary>
public class AwaitAsynClassNew

{
public void Show()
{
Console.WriteLine($"This Main Start {Thread.CurrentThread.ManagedThreadId}");
{
Console.WriteLine(ReturnLongAwait().Result);
}
Console.WriteLine($"This Main End {Thread.CurrentThread.ManagedThreadId}");
}

/// <summary>
/// 没有返回值--在方法里开启了一个Task线程
/// </summary>
public async void NoReturn()
{
Console.WriteLine($"This NoReturn Start {Thread.CurrentThread.ManagedThreadId}");
Task task= Task.Run(() => {
Console.WriteLine($"This NoReturn Task Start {Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(2000);
Console.WriteLine($"This NoReturn Task End {Thread.CurrentThread.ManagedThreadId}");
});
//await task;
task.ContinueWith(t => { Console.WriteLine($"End"); });
Console.WriteLine($"This NoReturn End {Thread.CurrentThread.ManagedThreadId}");
}
public async Task ReturnTask()
{
Console.WriteLine($"This ReturnTask Start {Thread.CurrentThread.ManagedThreadId}");
Task task = Task.Run(() => {
Console.WriteLine($"This ReturnTask Task Start {Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(2000);
Console.WriteLine($"This ReturnTask Task End {Thread.CurrentThread.ManagedThreadId}");
});
await task;
//Task的子线程完成的 如果没有await 那么应该是调用线程执行
//可以认为,加了await 就等同于将await后面的代码,包装成一个回调--其实回调的线程局部多种可能性
Console.WriteLine($"This ReturnTask End {Thread.CurrentThread.ManagedThreadId}");

await Task.Run(() => {
Console.WriteLine($"This ReturnTask2 Task Start {Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(2000);
Console.WriteLine($"This ReturnTask2 Task End {Thread.CurrentThread.ManagedThreadId}");
});
Console.WriteLine($"This ReturnTask End2 {Thread.CurrentThread.ManagedThreadId}");
//如果再来更多层的await,这个执行顺序,我们心里应该有谱了!
//可以用同步编码的形式去写异步
}

public long ReturnLong()
{
long result = 0;
Console.WriteLine($"This NoReturnLong Start {Thread.CurrentThread.ManagedThreadId}");
Task.Run(() => {
Console.WriteLine($"This NoReturnLong Task Start {Thread.CurrentThread.ManagedThreadId}");

for (int i = 0; i < 10000000; i++)
{
result += i;
}
Console.WriteLine($"This NoReturnLong Task End {Thread.CurrentThread.ManagedThreadId}");
return result;
});
Console.WriteLine($"This NoReturnLong End {Thread.CurrentThread.ManagedThreadId}");
return result;
}

public async Task<long> ReturnLongAwait()
{
long result = 0;
Console.WriteLine($"This NoReturnLongAwait Start {Thread.CurrentThread.ManagedThreadId}");
await Task.Run(() => {
Console.WriteLine($"This NoReturnLongAwait Task Start {Thread.CurrentThread.ManagedThreadId}");

for (int i = 0; i < 10000000; i++)
{
result += i;
}
Console.WriteLine($"This NoReturnLongAwait Task End {Thread.CurrentThread.ManagedThreadId}");
return result;
});

Console.WriteLine($"This NoReturnLongAwait End {Thread.CurrentThread.ManagedThreadId}");
return result;
}
}
}